2012-05-26 11 views
7

Dire che abbiamo questo codicePerché il cast di stile C ti consente di convertire in una classe base privata?

class A { 
public: 
    A() : x(1) {} 
    virtual ~A() {} 

    int x; 
}; 

class B { 
public: 
    B() : y(2) {} 
    virtual ~B() {} 

    void g() 
    { 
     cout << "B::" << y << endl; 
    } 

    int y; 
}; 

class C : private A, private B { 
public: 
    void f() 
    { 
     B* p = static_cast<B*>(this); 
     p->g(); 
    } 
}; 

int main() 
{ 
    C c; 
    ((B*)&c)->g(); 

    return 0; 
} 

Il cast stile C nella funzione principale non può essere espresso correttamente in termini di C++ calchi (static_cast, dynamic_cast, reinterpret_cast). Ma qual è la ragione per consentire questo in primo luogo? Non fa male l'incapsulamento?

UPDATE Questo non è un duplicato della domanda legato, perché questa questione è di circa decisioni di progettazione in C++. Non chiede cosa posso o non posso fare con la lingua, mi chiede perché certe decisioni potrebbero essere state prese.

+5

Poiché i cast in stile C sono troppo potenti e non dovrebbero mai essere utilizzati, ecco perché. –

+0

@CatPlusPlus, questo è esattamente il mio punto, perché ricevono così tanto potere? – unkulunkulu

+0

@unkulunkulu perché questo è C++. –

risposta

1

È perché in C è stato consentito convertire qualsiasi puntatore in qualsiasi altro puntatore utilizzando questo cast e C++ tenta di essere il più possibile compatibile con C, ma cerca di fare un buon lavoro per essere corretto quando si tratta di classi , quindi il cast di stile C è più forte di reinterpret_cast in questa situazione.

+0

Questo non è un comportamento corretto. –

+0

ok, ho capito la risposta subito dopo la pubblicazione, è C heritage, ok, ho capito: D – unkulunkulu

+0

@CatPlusPlus, intendo che modifica opportunamente il valore del puntatore – unkulunkulu

7

Quando un cast di puntatore in stile C viene utilizzato tra i puntatori a una classe di base e derivata, si comporta come un static_cast - anche se la base è privata.

(i cast di tipo C tra tipi di puntatori non collegati sono reinterpret_cast s).

Lo Standard dice:

Le conversioni eseguite da

- un const_cast (5.2.11),

- uno static_cast (5.2.9),

- un static_cast seguito da const_cast,

- reinterpret_cast (5.2.10) o

- un reinterpret_cast seguito da un const_cast,

può essere eseguita utilizzando la notazione cast di conversione di tipo esplicita. Le stesse restrizioni semantiche e comportamenti si applicano, con l'eccezione che in esecuzione di una static_cast nelle seguenti situazioni la conversione è valida anche se la classe base è inaccessibile:

- un puntatore ad un oggetto di tipo classe derivata o un lvalue o rvalue del tipo di classe derivata possono essere convertiti esplicitamente in un puntatore o in un riferimento a un tipo di classe base non ambigua, rispettivamente;

- un puntatore al membro del tipo di classe derivata può essere convertito esplicitamente in un puntatore al membro di un tipo di classe di base non virtuale non ambiguo;

- un puntatore a un oggetto di un tipo di classe di base non virtuale non ambiguo, un glivalue di un tipo di classe di base non virtuale non ambiguo o un puntatore a un membro di un tipo di classe di base non virtuale non ambiguo può essere convertito in modo esplicito a un puntatore, un riferimento o un puntatore al membro di un tipo di classe derivata, rispettivamente.

La situazione è descritta nel primo punto, quindi la conversione viene effettuata da static_cast e il puntatore viene regolato.

+0

Nota che un 'reinterpret_cast' su una classe base privata non è permesso. –

+0

'reinterpret_cast' ha dei limiti. –

+0

@ K-ballo per un puntatore? –

-1

Un cast di tipo C consente di convertire qualsiasi tipo in qualsiasi altro tipo. Puoi fare (std::istream*)&c se lo desideri, ma non è raccomandato.

+0

Quindi cosa puoi raccomandare al posto del cast di stile C nell'esempio nella domanda? – unkulunkulu

+0

Non si dovrebbe essere in grado di convertire un tipo in un tipo da esso ereditato privatamente. Dovresti usare l'ereditarietà pubblica se vuoi farlo. – robert

+0

Capisco che, da qui la domanda, riguarda le decisioni di progettazione in C++, non i buoni consigli sul codice :) Quindi penso che la mia risposta sia al punto. – unkulunkulu

Problemi correlati