2012-11-29 23 views
6

Possible Duplicate:
C++: overriding public\private inheritancefunzione virtuale privata nella classe derivata

class base { 
public: 
    virtual void doSomething() = 0; 
}; 

class derived : public base { 
private: // <-- Note this is private 

    virtual void doSomething() 
    { cout << "Derived fn" << endl; } 
}; 

Ora, se faccio la seguente:

base *b = new child; 
b->doSomething(); // Calls the derived class function even though that is private 

Domanda:

  1. E 'in grado di chiamare la funzione classe derivata anche se è privato. Com'è possibile?

Ora, se posso cambiare lo specificatore di accesso eredità dal pubblico al protetta, ottengo un errore di compilazione/privato:

'type cast' : conversion from 'Derived *' to 'base *' exists, but is inaccessible 

Nota: Sono consapevole dei concetti di specificatori di accesso eredità. Quindi nel secondo caso come derivato privato/protetto, è inaccessibile. Ma mi chiedo sulla risposta alla prima domanda. Qualsiasi input sarà molto apprezzato.

risposta

6

Il controllo di accesso è implementato in fase di compilazione, non in fase di esecuzione, mentre il polimorfismo (compreso l'uso di funzioni virtuali) è una funzionalità di runtime.

+0

Penso che voglia sapere perché lo specificatore di accesso funziona in questo modo piuttosto che sapere qual è la fonte dell'errore. – Hossein

6

Nel primo caso il controllo dell'accesso viene eseguito (come sempre avviene) sul tipo statico tramite il quale viene effettuata la chiamata. Il tipo statico di *b è base e in tal caso doSomething() è public.

C++ 03 11.6 "L'accesso alle funzioni virtuali" afferma:

The access rules (clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [Example:

class B { 
public: 
    virtual int f(); 
}; 

class D : public B { 
private: 
    int f(); 
}; 

void f() 
{ 
    D d; 
    B* pb = &d; 
    D* pd = &d; 

    pb->f(); //OK:B::f()is public, 
      // D::f() is invoked 
    pd->f(); //error:D::f()is private 
} 

—end example]

Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.

Tenete a mente in particolare che "l'accesso della funzione membro della classe in cui è stato definito (D nell'esempio di cui sopra) non è generalmente noto ". In generale, nel punto dell'esempio in cui viene chiamato b->doSomething();, il compilatore potrebbe non avere alcuna conoscenza di derived (o child), tanto meno se l'accesso a derived::doSomething() è privato o meno.

0

Le funzioni private sono pensate per essere nascoste dal mondo esterno e dalle classi derivate. Sebbene tu stia ignorando lo specificatore di accesso del DoSometing del genitore e rendendolo privato, stai creando un'istanza di una classe base; quindi nel primo caso, puoi chiamare DoSomething di base come è pubblico. Questo scenario può essere utilizzato se si desidera impedire alle persone derivate dalla classe derivata.

Nel secondo caso, lo specificatore di accesso private impedisce ai membri della base di essere esposti agli utenti della classe derivata, il che rende la classe derivata inutilizzabile.

+0

L'OP ha detto abbastanza chiaro ** È in grado di chiamare la funzione di classe derivata **. La tua speculazione su ** puoi chiamare DoSomething di base in quanto è pubblica ** è errata in base all'esempio dato e non è una risposta alla domanda 1. – StahlRat

Problemi correlati