Autor Thema: C++ Pointer auf Funktionen  (Gelesen 7778 mal)

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« am: 15. May 2005, 12:25 »
Also ich habe folgendes Problem:
Ich habe eine Klasse in der neben den normalen Funktionen etc, auch Zeiger auf Funktionen enthalten sein sollen, weil die Funktionen austauschbar sein müssen, da diese erst während der Laufzeit geladen werden. Diese Funktionen brauchen allerdings den Zugriff auf die anderen Memberdaten. Wollte es zuerst so machen, das die Funktionszeiger auf nicht-Member-Funktionen zeigen und denen als erster Parameter ein Zeiger auf die Klasseninstanz übergeben wird, ging nur nicht so recht. Dann dachte ich, man könnte in der Klasse definieren, dass wir einen Pointer auf eine Memberfunktion haben, damit der this-Zeiger automatisch mit übergeben wird. Dann stellt sich allerdings das Problem dass ich nicht weiss wie ich dann  die Funktionen deklarieren muss, denn die sollen ja wissen, das sie Mitglieder einer Klasse sind. Ich hoffe ihr habt mein Problem verstanden und wisst irgendwie ne Möglichkeit.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 15. May 2005, 12:39 »
Ich hab dein Problem nicht verstanden, aber ich zeige einfach
mal nen Weg auf, wie das so mit Pointern auf Memberfunktionen läuft:



class foo
{
public:
void bar()
{}
};

// definiere Typen pointer auf memberfunktion von foo, die void zurückgibt und keine Argumente übernimmt
typedef void (foo::*FOO_MEMBER_METHOD)();

int main()
{
FOO_MEMBER_METHOD pfnBar = foo::bar;
foo einFoo;
foo *pEinFoo = &einFoo;
(einFoo.*pfnBar)(); // direkter Aufruf
(pEinFoo->*pfnBar)(); // Aufruf über Zeiger

return 0;
}



MfG
DDR-RAM

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #2 am: 15. May 2005, 12:46 »
Ich will den zeiger IN der Klasse haben so
class p
{
public:
void (*f)(p*);
};

Die will ich verändern, ist ja so auch kein Problem nur greifts scheinbar nicht richtig auf die klassenmember dann zu, aufrufen kann ich sie ja richtig
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 15. May 2005, 12:50 »
Hi Roshl,

wenn du für dein Programm keine wirkliche Objektorientierung verwendest, dann solltest du C für das Programm benutzen, denn da geht es so wie du denkst.
In C++ macht es keinen einzelne Methoden während der Laufzeit auszutauschen. Dafür hast du aber die Möglichkeit eine ganze Klasse auszutauschen. Du kannst ja in deinem Programm eine Dummy oder auch abstrakte Klasse für deine Funktionalität implementieren und dann davon abgeleitete, voll funktionsfähige Klassen zur Laufzeit nachladen. Das funktioniert auf jeden Fall, ich weis nur nicht ob dein -problem so designt ist, dass es sich damit lösen lässt.

Gruß
n3Ro
Agieren statt Konsumieren!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #4 am: 15. May 2005, 12:54 »
Es macht wohl Sinn das zur Laufzeit auszutauschen. Denn ich will die Funktionen ja nicht beim compilen schon drin haben, sondern später dynamisch dazulinken. Ich will ja nicht die Klassen austauschen. Denn die sind ja bis auf die letztlichen Funktionen gleich.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

DDR-RAM

  • Beiträge: 184
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 15. May 2005, 12:58 »
Vielleicht hilft der Code:


#include <iostream>

class foo
{
public:
foo() :
m_pfnBar(bar1)
{}

protected:
void bar1()
{
std::cout << "bar1" << std::endl;
}
void bar2()
{
std::cout << "bar2" << std::endl;
}

public:
void CallBar()
{
(this->*m_pfnBar)();
}

public:
void SetBar1()
{
m_pfnBar = foo::bar1;
}
void SetBar2()
{
m_pfnBar = foo::bar2;
}

protected:
void (foo::*m_pfnBar)();
};

typedef void (foo::*FOO_MEMBER_METHOD)();

int main()
{
foo meinFoo;
meinFoo.CallBar();
meinFoo.SetBar2();
meinFoo.CallBar();
meinFoo.SetBar1();
meinFoo.CallBar();

return 0;
}

Was soll das sein?

void (*f)(p*);

eine MemberVariable, f, die ein pointer auf eine funktion hat, die ein p übernimmt.

MfG
DDR-RAM

n3Ro

  • Beiträge: 288
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 15. May 2005, 13:04 »
Funktional betrachtet macht es Sinn, aber nicht Objektorientiert. Du brauchst die Funktionen auch nicht beim compilieren drin haben. Das Programm muss nur wissen, wie die abgeleitete Klasse die es dazu lädt angesprochen werden muss, und dass sagst du dem Programm indem du es als einen Pointer auf seine Oberklasse defninierst.
Agieren statt Konsumieren!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #7 am: 15. May 2005, 13:06 »
Nein hilft mir auch nicht, habt mein Problem scheinbat nicht ganz verstanden. Aber egal ich hab rausgefunden, dass es doch funktioniert wie ichs machen wollte, hatte einen Fehler viel weiter vorher bei dem normalerweise es nicht hätte weitergehen dürfen, Bochs ist aber weitergegangen, seltsamerweise. Naja jetzt weiss ich wie ichs machen werde.
void (*f)(p*); ist ein Pointer auf eine Funktion die ein pointer auf eine klasse p nimmt und nix zurückgibt.
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

GhostCoder

  • Beiträge: 187
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 15. May 2005, 13:38 »
Hi,

Ich finde den Code auch irgendwie sinnlos :)
C++ ist doch dafür ausgelegt, dynamische Memberfunktionen zu haben, da ist so ein Kontrukt doch viel zu umständlich.

Zitat

Es macht wohl Sinn das zur Laufzeit auszutauschen. Denn ich will die Funktionen ja nicht beim compilen schon drin haben, sondern später dynamisch dazulinken. Ich will ja nicht die Klassen austauschen. Denn die sind ja bis auf die letztlichen Funktionen gleich.

Das meinte n3Ro ja auch (denke ich jedenfalls :) ).

Also so:
1. Basisklasse mit den dynamischen Funktionen als rein virtuell definiert.
2. Jedes Modul hat eine eigene abgeleitete Klasse, die die virtuellen Funktionen der Basisklasse ersetzt.
3. Jedes Module hat eine Funktion GetInstance(), die Zeiger auf die abgeleitete Klasse zurückgibt, aber als Basisklasse referenziert wird.

So arbeitest du im Kernel immer nur mit Instanzen der Basisklasse, "intern" werden aber die eigenen Funktionen der abgeleiteten Klassen benutzt. Einfacher und praktischer geht es wohl kaum...

Gruß GhostCoder
A man, a legend!

Roshl

  • Beiträge: 1 128
    • Profil anzeigen
    • http://www.lowlevel.net.tc
Gespeichert
« Antwort #9 am: 15. May 2005, 14:05 »
Kapier ich irgendwie nicht ganz^^
[schild=1]Wieder ein wertvoller(?) Beitrag von Roshl[/schild]

Legend

  • Beiträge: 635
    • Profil anzeigen
    • http://os.joachimnock.de
Gespeichert
« Antwort #10 am: 15. May 2005, 19:29 »
Also, wohl besser (meiner Meinung nach) geht das mit ner Factory. (ANMERKUNG: hatte das 2 posts über mir nicht gelesen, da steht im prinzip das selbe)

Ich nehme an, das du eigentlich Vererbung und virtuelle Funktionen benutzen würdest, wenn du das ganze nicht dynamisch laden würdest. Das geht auch mit dynamischem laden.

Host:

class IKlasse {
public:
         virtual ~IKlasse ();

         virtual void test () = 0;
};


Dann in dem Modul:

class Implementation : public IKlasse {
           virtual void test ();

           static IKlasse* factory ();
};


IKlasse* Implementation::factory ()
{
          return (new Implementation ());
}


soo, jetzt musst du nur noch dafür sorgen das die factory-funktion geladen wird und die du diese aufrufst, um dein richtiges Objekt zu erhalten. Evtl. wäre es auch eine möglichkeit, die als C funktion in einem extern "C" { ... } block zu packen.
*post*

 

Einloggen