2010-02-22 16 views
6

Il seguente codice restituisce un errore di compilazione per void b() { m = &A::a; }; che indica che A::a() è protetto. (Il che è - ma non dovrebbe essere un problema)
Tuttavia al compilatore non interessa quando scrivo B::a(). Anche se entrambi lo stesso significato io preferirei A::a() perché afferma esplicitamente che a() è definito in A.Perché non è possibile memorizzare un puntatore a funzione di una classe base?

Quindi qual è la ragione per cui è vietato A::a()?
EDIT
Forse qualcuno può trovare un esempio che potrebbe essere problematico se A::a() è stato permesso in B::b(). Se c'è un esempio, lo contrassegnerò come risposta alla domanda.
/EDIT

#include <iostream> 
#include <iomanip> 
#include <string> 
#include <cstdio> 

class A { 
protected: 
    void a(){ std::cout << "A::a()" << std::endl; }; 
}; 

typedef void (A::*f)(); 
class B : public A { 
public: 
    void b() { m = &A::a; }; // wont compile 
    // void b() { m = &B::a; }; // works fine 
    void c() { (this->*m)(); }; 
protected: 
    f m; 
}; 

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

// compile with 
// g++ -Wall main.cpp -o main 

Spiegazione del codice:
In B Voglio memorizzare un puntatore a funzione a un metodo in A per essere in grado di chiamare che più tardi in B::c(). E sì, questo succede anche nella vita reale. :-)

+0

Divertente ... accade sia con 'gcc-3.4.2' che' gcc-4.3.2' –

+0

può essere correlato a http://stackoverflow.com/questions/477829/cannot-call-base-class-protected-functions/477868#477868 – josefx

risposta

1

Il motivo dovrebbe essere simile a cui non si può fare questo in B sia:

class B: public A 
{ 
    //... 
    void foo(A& x) { 
     x.a(); //error 
    } 

    void foo(B& x) { 
     x.a(); //OK 
    } 
}; 

Che protetta non significa che B può accedere al Una parte di ogni classe purché sia un A/derivato da A. Il materiale protetto è disponibile solo per questa e altre istanze di B.

2

Perché altrimenti il ​​mondo esterno può trovare questo membro protetto: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11174.

Vedere anche http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00610.html.

+0

Hmm, nella mia ignoranza non riesco ancora a vedere perché è necessario. Il puntatore-funzione e quindi il metodo sono ancora protetti in B. Quindi non è accessibile dall'esterno e se fosse così sarebbe 'B :: b()' o mi manca completamente il punto? – Pascal

+0

@ tuner07, la protezione di accesso è determinata dal tipo statico dell'espressione. Il contesto reale in cui si prende il puntatore a funzione non entra in gioco. –

+0

@gf Se la protezione di accesso è determinata dal tipo statico dell'espressione, non dovrebbe essere possibile chiamare 'A :: a()' ovunque in B. Ma ciò è possibile. Quindi la regola si applica solo al caso in cui una funzione è memorizzata in un puntatore di funzione. Non vedo ancora alcun motivo per cui 'A :: a()' deve essere impedito dal compilatore. – Pascal

0

Si tenta di accedere al membro protetto tramite lo spazio dei nomi globale (A :: a is :: A :: a qui), utilizzare invece B :: A :: a.

+0

ancora non funziona. almeno con gcc-3.4.4. – Pascal

Problemi correlati