2016-05-04 6 views
1
class foo{ 
    public: 
    int n; 
    private: 
    virtual void sayHi(){ 
     cout<<"Hi there!"; 
    } 

}; 

Wie bekomme ich die Adresse von sayHi() ??Zugriff auf eine private virtuelle Member-Funktion über Zeiger

main(){ 
foo f; 
typedef void(*fptr)(); 
fptr func = reinterpret_cast<fptr>((&f)[0]); 
(*func)(); 
} 

Der obige Code hat nicht funktioniert.

Ich weiß, dass die ersten 8 Bytes von "f" -Objekt ist ein Zeiger auf eine virtuelle Tabelle, wo es die Zeiger auf die Funktionen enthält, verwende ich 64-Bit-Maschine. Ich versuche im Prinzip den sayHi() durch seinen Zeiger aufzurufen, anstatt ihn direkt von f aus aufzurufen, da sayHi() sowieso privat ist! Wie würde ich das tun? Teile ich es richtig auf ??

+0

Sprechen wir über Standard-C++ oder C++ auf Ihrem spezifischen c Compiler, Betriebssystem und Prozessorarchitektur? – immibis

+0

Ich benutze 64-Bit-Maschine. Aber es ist in Ordnung mit dem Standard-C++. Vielen Dank! –

+3

@Noor Thabit: Äh ... Nichts kann in "Standard C++" getan werden. Standard C++ hat nicht einmal ein Konzept der "virtuellen Tabelle". – AnT

Antwort

0

Nun, ISO C++ verbietet die Übernahme der Adresse einer gebundenen Member-Funktion, um einen Zeiger auf Member-Funktion zu bilden. Sie können jedoch so etwas tun, wenn es hilft. Sie können das Ergebnis überprüfen here.

#include <iostream> 
using namespace std; 

class foo{ 
    int n; 
public: 
    virtual void sayHi(){ 
     cout<<"Hi there!"; 
    } 
}; 

typedef void(*fptr)(); 

int main() { 
    auto func = reinterpret_cast<fptr>(&foo::sayHi); 
    (*func)(); 
    return 0; 
} 
+1

Dies ist kein tragbarer Code und wird wahrscheinlich nicht zur Laufzeit funktionieren. Sie weisen einem unformatierten Zeiger einen Zeiger-zu-Methode zu, indem Sie eine Typumwandlung verwenden, um zu verhindern, dass sich der Compiler über etwas beschwert, das möglicherweise illegal und gefährlich ist. Und Sie können eine nicht statische Klassenmethode, die einen unformatierten Zeiger verwendet, nicht aufrufen *, die Aufrufliste wird nicht korrekt eingerichtet. –

+0

Danke für den Kommentar! Deine Lösung funktioniert! Die Funktion muss jedoch privat sein! –

2

Sie können nicht einfach einen Zeiger auf eine nicht statische Elementfunktion haben und sie ohne ein Objekt aufrufen. Der straight-forward Weg, um Ihre Frage zu interpretieren würde ein pointer-to-member wie in werden:

auto fptr = &foo::sayHi; 
foo f; 
(f.*fptr)(); 

Nun, Sie sagen, Sie es nennen wollen, ohne durch f zu gehen. Es ist nicht klar, was das genau bedeutet. eine Lambda zu verwenden ist wahrscheinlich gut genug, um eine aufrufbar zu erstellen, wie Sie arbeitet

wollen
auto func = [] { return foo{}.sayHi(); }; 
func(); // call 

oder ein bestimmtes Objekt verwenden und es durch Bezugnahme (gezeigt) oder durch Wert

foo f; 
auto func = [&f] { return f.sayHi(); }; 
func(); 
+1

Danke für die Antwort! Aber es hat nicht funktioniert. –

+0

@NoorThabit: Warum nicht? –

+0

Kann sein, weil 'sayHi' privat ist! @MooingDuck –

1

sayHi() ist eine Erfassung -statische Methode einer Klasse Sie müssen eine Zeiger-zu-Methode anstelle eines unformatierten Zeigers verwenden (die Implementierung eines Methodenzeigers ist Compiler-spezifisch, vorausgesetzt, das interne Layout des Zeiger-zu-Methode ist nicht portierbar).

Auch sayHi() ist privaten-foo, so main() nicht direkt zugreifen können. Sie müssen entweder:

  1. erklären sayHi() als öffentliche:

    class foo 
    { 
        int n; 
    public: 
        virtual void sayHi(){ 
         cout << "Hi there!"; 
        } 
    }; 
    
    int main() 
    { 
        typedef void (foo::*fptr)(); 
        fptr func = &foo::sayHi; 
        foo f; 
        (f.*func)(); 
        return 0; 
    } 
    
  2. main() eine friend von foo sein machen:

    class foo 
    { 
        int n; 
        virtual void sayHi(){ 
         cout << "Hi there!"; 
        } 
        friend int main(); 
    }; 
    
    int main() 
    { 
        typedef void (foo::*fptr)(); 
        fptr func = &foo::sayHi; 
        foo f; 
        (f.*func)(); 
        return 0; 
    } 
    
+0

Danke für die Mühe. Aber sayHi() ist privat! –

+0

@Remy Der Code würde nicht kompilieren! –

+0

@EissaN .: Der Code kompiliert für mich gut, vorausgesetzt, 'sayHi()' wird als 'public' deklariert, oder wenn' main() 'als' friend' von 'foo' deklariert wird, ansonsten' main() 'kann nicht darauf zugreifen. –