Übergeben einer Klasse member-Funktion als Funktion der parameter
Ich habe 2 C++ - Klassen-Fragen:
Die 1. Frage ist: Wie kann ich es machen, damit ich Vorbeigehen kann, ein Klasse member-Funktion als parameter in eine andere Funktion, die & wie kann ich dann/rufe diese Funktion? Und wie kann ich das gleiche tun mit einer Klasse statische Funktion. Es vielleicht leichter zu verstehen, meine Frage mit Blick auf diese code:
class DebuggingManager
{
string testLog;
bool test1()
{
//run test & return whether it passed or failed
}
static bool test2()
{
}
//How can I call a member function?
void catalogueTest( string testName, bool DebuggingManager::*nMemberFunction )
{
testLog += "Status of " + testName + ": " + ((*)nMemberFunction()) + "\n";
}
//How can I call a static function?
void catalogueTest( string testName, bool DebuggingManager::*nStaticFunction )
{
testLog += "Status of " + testName + ": " + DebuggingManager::nStaticFunction() + "\n";
}
//how do I pass a member function or a static function as a parameter in another function
bool runTests()
{
catalogueTest( "Test of member functin", test1() );
catalogueTest( "Test of static functin", test2() );
}
};
Die 2. Frage ist: Ist es schlimm(oder gefährlich) Praxis zu nennen, ein Schüler (oder statische) Funktion indirekt wie oben. Ich habe das Gefühl, das ist wirklich eine schlechte C++ - Praxis?
BEARBEITEN: Durchführung von Beratung
Danke für die Antwort, habe ich versucht zu implementieren, die Beratung, seine eine Menge in meinen Kopf zu kriegen, würde dies korrekt sein?
//I have a feeling that ParameterList is incorect, would I pass the implicit obj as a parameter or is it done automatically like in normal object function calls?
typedef bool (DebuggingManager::*MemberPointerType)(ParameterList);
void catalogueTest( tstring testName, DebuggingManager* obj, MemberPointerType *nMemberFunction )
{
debugLog += _T("Status of ") + testName + _T(": ") + (obj->*nMemberFunction)() + _T("\r\n");
}
void catalogueStaticTest( tstring testName, bool DebuggingManager::nStaticFunction )
{
debugLog += _T("Status of ") + testName + _T(": ") + nStaticFunction + _T("\r\n");
}
- Ich bin überrascht, dass dies nicht bereits beantwortet. Vielleicht jeder andere ist müde und will nicht, um die syntax für die Funktion Zeiger für den 500sten mal.
- siehe stackoverflow.com/questions/2463112/... gibt einen link zu parashift.com/c++-faq-lite/pointers-to-members.html die die syntax und die Dinge zu achten, wenn die Deklaration/Verwendung von normal-und statische member-Funktion-Zeiger. Als ob es schlecht würde ich sagen: wahrscheinlich nicht in einem bestimmten Fall (wie testen, oder vielleicht andere), aber es wäre nicht gut zu tun, wie ein Tag-zu-Tag Praxis für das schreiben von code, da es schwierig ist, und da gibt es bessere Mechanismen, die für die meisten alles, was Sie würden Sie für den Einsatz.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Statische member-Funktionen von Klassen sind letztlich nicht anders als normale Funktionen. Sie sind wirklich nur syntaktischer Zucker; die Funktion ist einfach die einen Namen hat, gehören
Classname::
.Nicht-statische member sind eine ganz andere Sache. Es gibt zwei wichtige Dinge zu erinnern, über die nicht-statische member-Funktionen (NSMF).
Zunächst jedes nicht-statische member-Funktion hat Zugriff auf nicht-statische member der Klasse, in der Sie Mitglied sind. Dies ist möglich, obwohl Sie können auch zwei Objekte derselben Klasse, die zufällig zum speichern verschiedener Daten. Wenn Sie zwei
std::string
Objekte, die Sie jedem Shop unterschiedliche Zeichenfolgen. Ausführen einerfind
auf der einen string zurückgeben kann gefunden in einer Folge, aber nicht die anderen.Dies ist, weil jeder NSMF hat eine implizite
this
Zeiger.this
bezieht, nicht nur eine Klasse, sondern die tatsächliche Objekt auf die, die NSMF betreibt. Wenn Sie dies tun:Den
find
- Funktion nimmt einen string-argument, aber es wird auchaString
als seinethis
. Jedes mal, wennfind
sieht für die Mitglieder der Klasse, es wird gesuchtaString
's Daten.Also schauen wir uns an Ihren zukünftigen Ruf eines NSMF:
Wo ist das Objekt, das es bekommt seine
this
Zeiger aus? Ohne ein Objekt, das NSMF konnte nicht auf die nicht-statische member des Objekts, da es kein Objekt für Sie zu finden, Sie in. Dies ist nicht legal.So, Regel #1 zu NSMFs: Sie muss rufen Sie mit einem aktuellen Instanz der Klasse, die NSMF ist ein Mitglied (oder eine abgeleitete Klasse davon). Sie können nicht nehmen Sie nur eine NSMF Zeiger und nennen es wie ein Funktionszeiger; Sie rufen es auf einem live-Objekt von diesem Typ.
Regel #2: die syntax für NSMF Zeiger ist wirklich hässlich.
Definieren Sie eine variable (oder argument) mit dem Namen
arg
von NSMF Zeiger geben Sie dies tun:Wo
ReturnType
ist der Rückgabetyp der Funktion,ParameterList
ist die Liste von Argumenten, die Funktion und dieClassName
ist der name der Klasse, zu der die NSMF Zeiger gehört.Angesichts der Hässlichkeit, ist es normalerweise am besten, um wickeln Sie es in ein typedef:
Somit die typedef
MemberPointerType
, das ist ein NSMF Zeiger.Gegeben ein Objekt mit dem Namen
object
, die den TypClassName
rufen Sie das Mitglied Zeigerarg
wie folgt:Wo
Params
sind die Argumente, die Sie übergeben möchten. Wennobject
ist ein Zeiger auf eineClassName
statt eine Referenz oder einen Wert, dann verwenden Sieobject->*arg
statt.Eins noch: Sie muss verwenden
&
um die member-Zeiger-Namen. Im Gegensatz zu Funktionszeigern, NSMF Zeiger nicht automatisch konvertieren member-Zeiger. Sie haben Fragen, für die Sie direkt. Also, wennClassName
hat ein Mitglied namens Funktion, passen die oben genanntenReturnType
undParameterList
Sie füllen würdearg
wie folgt:Regel #3: nicht-statische member-Zeiger sind keine Zeiger. Ja, Sie können auf NULL gesetzt werden (technisch, Sie kann auf 0 gesetzt werden), aber Sie sind nicht das gleiche wie ein Zeiger.
Meisten realen C-und C++ - Compiler ermöglichen Ihnen die cast-Funktion Zeiger auf eine
void*
- und Rückseite. Die standards berücksichtigen Sie dies zu undefiniertem Verhalten, aber es ist nicht-ganz-unbekannt, dies zu tun. Sie absolut nicht dies mit einer NSMF Zeiger, die auf praktisch allen C++ - Compilern. In der Tat, diesizeof(MemberPointerType)
wird wahrscheinlich nicht die gleiche Größe wievoid*
.So, NSMF Zeiger sind keine gewöhnlichen Zeiger. Nicht behandeln Sie als solche.
(object.*arg)(Params);
weil der Rangfolge?.*
hat eine geringere Priorität als ein Funktionsaufruf.In C++ 11 kamen Sie mit einem Weg, dies zu tun. Lesen Sie über Funktion und binden Operationen.
In deinem Fall, sagen wir mal, Sie wollten zum aufrufen von Funktionen des Typs test1. (d.h. von der form bool-FunctionName().
- Und nennen es wie folgt: