Zeiger auf Funktion


Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

fujitsufan

Erfahrenes Mitglied
#1
Hallo zusammen,

weiß jemand ob ich in MFC einen Zeiger auf eine Funktion stellen kann.
In C++ mach ich da so.
C++:
//Zeiger auf GetPrintBasics oder GetTestBasics stellen dem Zweck entsprechend
CString(*pGetDocBasics)(CString, CString *);
pGetDocBasics = strPurpose == "TESTDOC" ? GetTestBasics : GetPrintBasics;
Selbst wenn ich die Deklarierung des Pointers als "typedef" mache meckert der Compiler.
Fehler C2440 "=": "CString (__thiscall CMainDialog::* )(CString,CString *)" kann nicht in "CString (__cdecl *)(CString,CString *)" konvertiert werden
Der Return (CString) und die Übergabeparameter (CString, CString*) sind aber korrekt.
Geht das in MFC überhaupt noch?

Vielen Dank
MfG.
fujitsufan
 

fujitsufan

Erfahrenes Mitglied
#3
Hallo -ComFreek,

die Deklaration des Pointers nimmt Gestalt an.
C++:
CString(__thiscall CMainDialog::*pGetDocBasics)(CString, CString *);
Vielen Dank dafür.
Jetzt besteht das Problem mit der Zuweisung.
Ich muss doch irgendwie dem Pointer die Adresse der aufzurufenden Funktion anvertrauen.
Die Compilermeldung widersprechen sich.

Mach ich die Zuweisung so,
C++:
pGetDocBasics = GetPrintBasics;
dann kommt die Meldung:
Fehler C3867 "CMainDialog::GetPrintBasics": Keine Standardsyntax; "&" zum Erstellen eines Verweises auf das Member verwenden.

Mach ich die Zuweisung so,
C++:
pGetDocBasics = &GetPrintBasics;
dann kommt die Meldung:
Fehler C2276 "&": Ungültige Operation auf Ausdruck einer gebundenen Memberfunktion.
Gibt es noch eine andere Möglichkeit für die Zuweisung?
Hab ich was verpasst?
Vielleicht fällt Dir noch was ein.

Mit freundlichen Grüßen
fujitsufan
 

ComFreek

Mod | @comfreek
Moderator
#4
Ich habe mal "c++ get pointer to class method" gegoogelt und fand den vielversprechenden Link: Calling C++ class methods via a function pointer

Die Zuweisung sollte also erst einmal so aussehen:
C++:
pGetDocBasics = &CMainDialog::GetPrintBasics
Der Aufruf ist dann so:
C++:
// myObject muss irgendeine Instanz sein, kann auch "this" sein
CMainDialog myObject;

(myObject.*pGetDocBasics)(cString, cStringPointer)

// Spezialfall this
(this->*pGetDocBasics)(cString, cStringPointer)
Methoden operieren ja bekanntlich immer auf Instanzen. Zum Aufruf einer Methode braucht man also immer eine Instanz. Rufst du eine Methode via "myObject.GetPrintBasics(...)" auf, so ist die Instanz myObject. Rufst du sie innerhalb einer anderen Methode via "GetPrintBasics(...)" auf, so steht das implizit für "this->GetPrintBasics(...)", was in den allermeisten Fällen [1] gleichbedeutend mit "(*this).GetPrintBasics(...)" ist. D. h. im letzten Beispiel ist "*this" (mit Derefenzierungsstern!) die Instanz.
Daher musst du auch bei pGetDocBasics "this" angeben.

Mein JavaScript-beeinflusstes-Bauchgefühl sagt mir jedoch, dass es doch einen einfacheren Weg mittels Lambdas geben muss. Ich habe gerade Folgendes versucht:
C++:
// In a member function (= "method")
void (*memberFunctionToCall)(int);
memberFunctionToCall = [this] (int param) { this->memberFunction1(param); };
Aber die zweite Zeile kompiliert aufgrund eines Typfehlers nicht. So wie ich den als C++ Laie interpretiere, bedeutet "[this]" nicht wirklich *nur* Capturing von this, sondern auch direkte Abstrahierung davon danach, d.h. die rechte Seite braucht trotzdem eine Instanz zum Ausführen.

Mein vollständiger Testcode war übrigens https://onlinegdb.com/SJdl9K9BE. (Falls einer der erfahreneren C++-Programmierer einen Blick auf den Fehler werfen möchte.)

[1]: Solange -> nicht gerade in der Klasse überladen ist.
 

fujitsufan

Erfahrenes Mitglied
#5
Hallo,

leider kann ich nicht auf den Zeiger zugreifen.
Weder über den this- Zeiger noch über den Klassennamen.
Es schein so zu sein, dass der Zeiger nicht auf die Klasse CMainDialog instanziert ist.

MFC ist hierfür zu komplex aufgebaut.
Bei C++, C#, Delphi usw. ist das alles kein Problem.

Trotzdem vielen Dank!
fujitsufan
 

ComFreek

Mod | @comfreek
Moderator
#6
leider kann ich nicht auf den Zeiger zugreifen.
Weder über den this- Zeiger noch über den Klassennamen.
Es schein so zu sein, dass der Zeiger nicht auf die Klasse CMainDialog instanziert ist.
Da du keine Fehlermeldung gepostet hast, kann ich dir leider auch nicht weiterhelfen.

MFC ist hierfür zu komplex aufgebaut.
Bei C++, C#, Delphi usw. ist das alles kein Problem.
MFC ist eine Bibliothek. Die Programmiersprache ist ein C++-Dialekt von Microsoft. Insofern kann es durchaus sein, dass du moderne C++-Konstrukte verwenden kannst, sofern die neuen VisualStudio Umgebungen noch MFC unterstützen.
 

fujitsufan

Erfahrenes Mitglied
#7
Hallo,

ist mir entgangen.
Hier der Code:
C++:
CString(__thiscall CMainDialog::*pGetDocBasics)(CString);
    pGetDocBasics = &CMainDialog::GetTestBasics;

    strTemp = pGetDocBasics("OrderNo2");
Und hier die Compiler Meldung:
Fehler (aktiv) E0109 Der Ausdruck vor den Klammern des sichtbaren Aufrufs muss einen Funktionstyp (pointer-to-) aufweisen

Fehler C2064 Ausdruck ergibt keine Funktion, die 1 Argumente übernimmt

MfG.
fujitsufan
 

ComFreek

Mod | @comfreek
Moderator
#8
Und hier die Compiler Meldung:
Fehler (aktiv) E0109 Der Ausdruck vor den Klammern des sichtbaren Aufrufs muss einen Funktionstyp (pointer-to-) aufweisen

Fehler C2064 Ausdruck ergibt keine Funktion, die 1 Argumente übernimmt
Leider hast du die Zeilennummern ausgelassen. Ich rate also mal, dass es die letzte Zeile betrifft.

In meinem Beitrag oben habe ich auch gezeigt, wie pGetDocBasics aufgerufen werden sollte.
 

ComFreek

Mod | @comfreek
Moderator
#10
Ich komme aber über den this - Zeiger nicht den Pointer (pGetDocBasics ) ran.
Diese Aussage hilft mir 0 weiter. Merke: Sätze wie "Das geht nicht" sind fast immer nutzlos ohne Code und ohne Fehlermeldung.

Folgender Code funktioniert: https://onlinegdb.com/B1wMUyiHN (bei dir müsstest du aber das mit __thiscall drinlassen!)
Sprich, probier das hier:
C++:
CString(__thiscall CMainDialog::*pGetDocBasics)(CString);
pGetDocBasics = &CMainDialog::GetTestBasics;

strTemp = (this->*pGetDocBasics)("OrderNo2");
 

fujitsufan

Erfahrenes Mitglied
#11
Hallo ComFreek,

sieht mal gut aus. Der Compiler meckert nicht.
Ich hatte es schon mal so ausprobiert.
C++:
strTemp = (*this->pGetDocBasics)("OrderNo2");
Den * an der falschen Stelle.
Ich vervollständige den Code erst am Montag.
Dann kann ich die das Ergebnis liefern.

Vielen Dank mal bis dahin.
MfG.
fujitsufan
 

fujitsufan

Erfahrenes Mitglied
#12
Hallo ComFreek,

läuft.

C++:
//Den Zeiger abhängig vom Zweck auf die erforderiche Funtion setzen
    CString(__thiscall CMainDialog::*pGetDocBasics)(CString);
    pGetDocBasics = strPurpose == "TESTDOC" ? &CMainDialog::GetTestBasics : &CMainDialog::GetPrintBasics;
Zugriff über den Zeiger:
C++:
strTemp = (this->*pGetDocBasics)("OrderNo2");
Vielen Dank nochmal für deine Hilfe.

Mit freundlichen Grüßen
fujitsufan
 
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…