problem mit functionpointer

cycovery

Erfahrenes Mitglied
hi!

Ich hab ne Klasse, deren Objekte in einer membervariable einen functionpointer speichern sollen, und es soll eine methode geben um den functionpointer ans objekt zu übergeben.

class MyClass {
public:
MyClass();
~MyClass();
double callFunction(int x, int y);
void setFunction(double (*newFunc)(int x, int y));

private:
double (*m_myFunctionPointer)(int x, int y);
}

MyClass::MyClass(){
double (MyClass::*m_myFunctionPointer)(int, int) = 0;
}

double MyClass::callFunction(int x, int y) {
if(*m_myFunctionPointer!=0){
return m_myFunctionPointer(x, y);
}
else{
return 0.0;
}
}

void MyClass::setFunction(double (*newFunc)(int, int)){
double (MyClass::*m_myFunctionPointer)(int,int) = &newFunc;
}


das problem ist die rote Zeile. ich kriege folgenden Compile error:

Error 1 error C2440: 'initializing' : cannot convert from 'double (__cdecl **__w64 )(int,int)' to 'double (__thiscall MyClass::* )(int,int)'



Kann mir jemand erklären, warum das nicht geht? und wie mans richtig (und schön) macht?
Danke!
 
Hi.

C++:
void MyClass::setFunction(double (*newFunc)(int, int)){
  m_myFunctionPointer = newFunc;
}
Bitte verwende die Code Tags!

Gruß

PS: Der Konstruktor sollte so aussehen:
C++:
MyClass::MyClass() : m_myFunctionPointer(0) {
}
 
Zuletzt bearbeitet:
Ich fande das Kapitel Funktionspointer relativ schwierig zu verstehen, kann mir wer sagen wofür das nützlich ist ? So kurzes Bsp. evtl. Danke :)
 
Ich fande das Kapitel Funktionspointer relativ schwierig zu verstehen, kann mir wer sagen wofür das nützlich ist ? So kurzes Bsp. evtl. Danke :)
Durch Funktionspointer kann man einen neuen Level von Indirektion einführen. Dies ist meist nützlich um komplexe Probleme zu erledigen. Bspw. muss ein Betriebssystem verschiedene Dateisysteme unterstützen (ISO9660 für CD-ROM, UFS, ext3, reiserfs etc.)

Die read Funktion könnte man naiv dann so implementieren:
C:
int read(FILESYS fs, int* buf, int size) {
  switch (fs.type) {
  case ISO9660:
    return read_iso9660(fs, buf, size);

  case ext3:
    return read_ext3(fs, buf, size);
  
  ... /* usw */
  }
}
Dieses Schema ist schlecht erweiterbar und schlecht wartbar. Falls ein neues Dateisystem hinzukommt sind alle Funktionen zu ändern (read, write, usw.).

Mit Funktionspointer in einer allgem. Struktur wird man der Sache viel besser gerecht:
C:
struct FILE_OP {
  FILE_SYS fs;

  int (*read)(FILE_SYS, int*, int);
  int (*write)(FILE_SYS, int*, int);
  /* ... usw. */
};
Jetzt könnte die allgemeine read Funktion so ausehen:
C:
int read(FILE_OP op, int* buf, int sz) {
  return (*op.read)(op.fs, buf, int);
}
Es muß jetzt nur einmal die Struktur für das entsprechende Dateisystem mit den Zeigern zu den richtigen Funktionen gesetzt werden und das war's dann auch schon. Ein weiterer Vorteil ist, das jetzt ein weiteres Dateisystem hinzugefügt werden kann ohne auch nur eine der read, write usw. Funktionen anzufassen.

Eine weitere nette Anwendung von Funktionszeigern sind Callback bei Fenstersystemen.

Gruß
 
Ok vielen Dank für das Beispiel, das Szenario habe ich verstanden trotzdem sieht das sehr "abstrakt" und nicht leicht verständlich aus. In dem Beispiel fehlt jetzt aber die eigentliche "read" Funktion die etwas ausliest aus dem Filesystem oder ? Bzw. mich verwirrt die gleiche Namensgebung. int read wird aufgerufen und ein Funktionspointer wird zurückgegeben ?
Mit dem kann man nun die richtige Fkt. aufrufen ?

mfg
 
Ok vielen Dank für das Beispiel, das Szenario habe ich verstanden trotzdem sieht das sehr "abstrakt" und nicht leicht verständlich aus. In dem Beispiel fehlt jetzt aber die eigentliche "read" Funktion die etwas ausliest aus dem Filesystem oder ? Bzw. mich verwirrt die gleiche Namensgebung. int read wird aufgerufen und ein Funktionspointer wird zurückgegeben ?
Nein, die Funktion auf die der Funktionspointer zeigt wird aufgerufen (also z.B. read_iso9660, read_ntfs etc.) und das Ergebnis von dem Aufruf wird zurückgegeben.

Das ist natürlich jetzt ein hypothetisches Beispiel. Das Betriebssystem kümmert sich natürlich um das Füllen der FILE_OP Struktur und die Benutzung der read, write etc. Funktionen ist für den Anwender völlig transparent - egal um welches Dateisystem es sich nun handelt.

Gruß
 
Zuletzt bearbeitet:
Zurück