2015-02-20 5 views
7

Hier versuche ich die Adresse der geschützten Member-Funktion der Basisklasse zu erhalten. Ich bekomme diesen Fehler.Geschützte Mitgliedsfunktionsadresse in abgeleiteter Klasse ist nicht zugänglich.

main.cpp: In member function ‘void B::bar()’: 
main.cpp:5: error: ‘void A::foo()’ is protected 
main.cpp:13: error: within this context 
make: *** [all] Error 1 

Ändern von foo zu öffentlichen Arbeiten. Auch Drucken &B::foo funktioniert. Können Sie bitte erklären, warum wir die Adresse der geschützten Member-Funktion der Basisklasse nicht bekommen können?

+0

Gute Frage.Scheint wie eine zukünftige Korrektur! – iammilind

Antwort

5

B ist Zugriff auf geschützte Mitglieder von A erlaubt, solange der Zugriff über ein Objekt vom Typ B erfolgt. In Ihrem Beispiel versuchen Sie, über A auf foo zuzugreifen, und in diesem Zusammenhang ist es unerheblich, ob B von A abgeleitet ist oder nicht.

Von N3337, §11.4/1 [class.protected]

Eine zusätzliche Zugangskontrolle über den früher 11 in Abschnitt beschrieben wird angewendet, wenn ein nicht-statisches Datenelement oder nicht-statischen Die Memberfunktion ist ein geschütztes Mitglied ihrer Benennungsklasse (11.2). Wie bereits beschrieben, wird früher, der Zugriff auf ein geschütztes Mitglied gewährt, da die Referenz in einem Freund oder Mitglied einer Klasse C vorkommt. Wenn der Zugriff einen Zeiger auf das Element (5.3.1) bilden soll, muss der Name der verschachtelten BezeichnungC oder eine Klasse sein, die von C abgeleitet ist. Alle anderen Zugriffe beinhalten einen (möglicherweise impliziten) Objektausdruck (5.2.5). In diesem Fall muss die Klasse des Objektausdrucks C oder eine von C abgeleitete Klasse sein. [Beispiel:

class B { 
protected: 
    int i; 
    static int j; 
}; 
class D1 : public B { 
}; 
class D2 : public B { 
    friend void fr(B*,D1*,D2*); 
    void mem(B*,D1*); 
}; 
// ... 
void D2::mem(B* pb, D1* p1) { 
    // ... 
    int B::* pmi_B = &B::i; // ill-formed 
    int B::* pmi_B2 = &D2::i; // OK 
    // ... 
} 
// ... 

-Ende Beispiel]

Ihr Beispiel ist sehr ähnlich zu dem Code in D2::mem, die zeigt, dass stattdessen einen Zeiger auf ein geschütztes Element durch B zu bilden versuchen, von D2 ist schlecht ausgebildet.

+0

Kann jemand die Syntax 'int B :: * pmi_B' erklären? Sind 'pmi_B' und' pmi_B2' int Werte oder sind sie Zeiger? Warum hast du 'B ::' vor dem Sternchen angerufen? – Sterling

+1

@Sterling Es ist ein [Zeiger auf Datenelement der Klasse B] (http://stackoverflow.com/a/670744/241631) – Praetorian

1

Scheint, dass ich die Antwort gefunden habe. Wenn wir den Zeiger der Elementfunktion erhalten könnten, können wir ihn für andere Objekte vom Typ A (nicht this) aufrufen, was nicht erlaubt ist.

Es ist nicht erlaubt, die Funktion protected member in abgeleiteten Klassen für andere Objekte als this aufzurufen. Zeiger zu bekommen würde das heftig machen.

Wir können etwas tun:

#include <iostream> 

class A { 
protected: 
    void foo() 
    {} 
}; 

class B : public A { 
public: 
    void bar() 
    { 
     void (A::*fptr)() = &A::foo; 

     A obj; 
     (obj.*fptr)(); 

     // obj.foo(); //this is not compiled too.  
    } 
}; 

int main() 
{ 
    B b; 
    b.bar(); 
} 
1

Ich war neugierig und versuchte das folgende Beispiel:

#include <iostream> 
using namespace std; 

class A { 
public: 
    void foo() 
    { 
    } 
}; 

class B : public A { 
public: 
    void bar() 
    { 
     printf("%p\n", (&A::foo)); 
     printf("%p\n", (&B::foo)); 
    } 
}; 

int main() 
{ 
    B b; 
    b.bar(); 
} 

Eigentlich sehe ich, dass &A::foo == &B::foo, so für den geschützten Teil des Basis Klasse können Sie abgeleitete Klassenmitglieder verwenden, um die Adresse zu übernehmen. Ich nehme an, im Fall von virtuellen Funktionen wird dies nicht funktionieren

Verwandte Themen