2015-02-20 14 views
7
#include <iostream> 

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

class B : public A { 
public: 
    void bar() 
    { 
     std::cout << (&A::foo) << std::endl; 
    } 
}; 

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

Qui sto cercando di ottenere l'indirizzo della funzione membro protetta della classe base. Sto ottenendo questo errore.L'indirizzo della funzione membro protetto nella classe derivata non è accessibile

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 

Modifica foo a lavori pubblici. Anche la stampa di &B::foo funziona. Puoi spiegare perché non possiamo ottenere l'indirizzo della funzione membro protetto della classe base?

+0

Buona domanda.Sembra una correzione futura! – iammilind

risposta

5

B è consentito l'accesso agli utenti protetti di A purché l'accesso venga eseguito tramite un oggetto di tipo B. Nell'esempio si sta tentando di accedere a foo tramite A e, in tale contesto, è irrilevante se lo B derivi da A oppure no.

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

viene applicato un controllo di accesso aggiuntivo oltre quelli descritti in precedenza nella clausola 11 quando un membro dati non statici o non statici la funzione membro è un membro protetto della sua classe di denominazione (11.2) Come descritto in precedenza , l'accesso a un membro protetto è concesso perché il riferimento si verifica in un amico o membro di qualche classe C. Se l'accesso è per formare un puntatore al membro (5.3.1), lo specificatore di nome nidificato indicherà C o una classe derivata da C. Tutti gli altri accessi implicano un'espressione dell'oggetto (possibilmente implicita) (5.2.5). In questo caso, la classe dell'espressione dell'oggetto deve essere C o una classe derivata da C. [Esempio:

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 
    // ... 
} 
// ... 

esempio -end]

vostro esempio è molto simile al codice in D2::mem, il che dimostra che il tentativo di formare un puntatore a un membro protetto attraverso B invece di D2 è mal formato.

+0

Qualcuno può spiegare la sintassi 'int B :: * pmi_B'? I valori int sono 'pmi_B' e' pmi_B2' o sono puntatori? Perché hai chiamato 'B ::' prima dell'asterisco? – Sterling

+1

@Sterling È un [puntatore al membro dei dati della classe B] (http://stackoverflow.com/a/670744/241631) – Praetorian

1

Sembra che abbia trovato la risposta. Se potessimo ottenere il puntatore della funzione membro, possiamo chiamarlo per altri oggetti di tipo A (non this) che non è consentito.

Non è consentito chiamare la funzione membro protetta nelle classi derivate per oggetti diversi da this. Ottenere puntatore sarebbe violento.

possiamo fare qualcosa di simile:

#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

ero curioso e provato il seguente esempio:

#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(); 
} 

In realtà, vedo che &A::foo == &B::foo, quindi per membro protetto della base classe puoi usare il membro della classe derivata per prendere l'indirizzo. Suppongo che in caso di funzioni virtuali questo non funzioni

Problemi correlati