2017-07-24 2 views
1

Nachstehend ist ein funktionierender Code dargestellt. Aber ich möchte "dieses" Schlüsselwort verwenden, um meine Funktionszeiger innerhalb meiner Implementierung (z. B. innerhalb der Konstruktorimplementierung) aufzurufen. Bitte helfen Sie mir, eine Lösung zu finden.Mit diesem Schlüsselwort auf Funktionszeiger in C++ zugreifen

Mein System ist g ++ (GCC) 4.1.2 20.080.704 (Red Hat 4.1.2-55)

Arbeits-Code

#include <iostream> 
#include <string> 
#include <map> 

using namespace std; 

class TestClass{ 
public: 
    typedef int (TestClass::*FunctionPtr)(int); 
    map <string, FunctionPtr> mFnPtrMap; 

    int Function1(int nAdd) { return nAdd + 1; } 
    int Function2(int nAdd) { return nAdd + 2; } 

    TestClass() { 
     mFnPtrMap.insert(make_pair("Function1", &TestClass::Function1)); 
     mFnPtrMap.insert(make_pair("Function2", &TestClass::Function2)); 
    } 

    int CallFunction(const string & s, int n) { 
     FunctionPtr fp = mFnPtrMap[s]; 
     return (this->*fp)(n); 
    } 
}; 

int main() { 
    TestClass ts; 
    cout << ts.CallFunction("Function1", 0) << endl; 
    cout << ts.CallFunction("Function2", 0) << endl; 
} 

Was ich tun möchte, ist:

Meine Erwartung ist, es in so etwas zu ändern (verwenden Sie 'this ->' anstelle von 'TestClass ::')

mFnPtrMap.insert(make_pair("Function1", &this->Function1)); 

Es gibt mir einen Compilerfehler. Es schlägt mir sogar vor, TestClass :: name resolution zu verwenden.

„ISO C++ verbietet das Ermitteln der Adresse eines gebundenen Elementfunktion Elementfunktion einen Zeiger zu bilden. Sprich & Testclass :: Function1“

Heißt das es bedeutet nicht möglich ist? Wenn mir jemand auch eine Erklärung geben könnte, würde es mir helfen, die darunter liegende Theorie zu verstehen. Vielen Dank.

+0

Warum wollen würden Sie diesen Namen anstelle der Klasse benutzen?Welchen Vorteil sehen Sie daraus? – HeroicKatora

+0

Wenn es nur darum geht, die explizite Verwendung des Klassennamens zu vermeiden, empfehle ich, 'decltype' und' std :: remove_pointer' zu verwenden, um sie aus 'this' zu rekonstruieren. Wie in C++ 11 können Sie den folgenden Code verwenden: 'std :: remove_pointer :: type' als Drop-In-Ersatz für den expliziten Klassennamen – HeroicKatora

+0

Es soll keinen Vorteil bringen. Ich möchte es in meinem Code nicht statisch aussehen lassen, nur um es an lokale Codierungsstandards anzupassen, denen wir folgen. – SajithP

Antwort

1

Wenn ich für einen Grund hinter diesem Teil des C++ - Standards erraten musste, ist es, dass die Arten von Ausdrücken kaum gleichwertig sind. Man vergleiche nur, wie Sie die Funktion, wenn in einem einzigen Ausdruck ohne Funktionsaufruf als eine Art Umleitung nennen müßten:

(this->*TestClass::function)(); // Binding the member pointer to an instance 

Hier haben wir das Element Zeiger auf eine Instanz mit dem ->* Operator binden, die die impliziten T* füllen Argument jede Member-Funktion hat, die eine this benannt. Eine andere Sprache bittet Sie, es explizit anzugeben, zum Beispiel Python, aber ich bin ein wenig abgelenkt.

this->function(); 

Hier die subexpression this->function gebunden bereits den Parameter von this an das lokale this Objekt, das bedeutet, dass dies in der Tat in keiner Weise auf eine Funktion beziehen. Folglich können Sie keine Adresse davon nehmen.

Sie könnten argumentieren, dass dies als Teil des Standards zulässig sein sollte, aber bedenken Sie, dass Sie Funktionsdeklarationen in untergeordneten Klassen überschreiben können. Das bedeutet, dass die Einführung eines zweiten Ausdrucks zum Ausdrücken &TestClass::function nur zu Verwirrung führen würde. In der aktuellen Form ist es sehr klar, welche function wir beziehen, während in einer this->function Form wäre es nicht, vor allem Neulinge könnten davon ausgehen, dass dies vollständig dynamisch ist, da this kein statisches Objekt ist. Es wäre auch nicht unangemessen anzunehmen, dass tatsächlich ein Unterschied zwischen den Ausdrücken besteht.

In der Zwischenzeit kann ich nur eine Möglichkeit bieten, die explizite Referal die Klasse von einigen Typ-Ebene Berechnungen zu entfernen:

#include <type_traits> 
template<typename T> 
using This = typename std::remove_const<typename std::remove_pointer<T>::type>::type; 

TestClass::TestClass() { 
    mFnPtrMap.insert(make_pair("Function1", &This<decltype(this)>::Function1)); 
    mFnPtrMap.insert(make_pair("Function2", &This<decltype(this)>::Function2)); 
} 
+0

wird nur ab C++ 11 unterstützt. Anyway +1 für Ihre Mühe und Erklärung. – SajithP

+0

@SajithP Es tut mir leid, ich habe keinen Weg gefunden, ohne die C++ 11-Funktion 'declltype' zu ​​verwenden. – HeroicKatora