Perché l'accesso alle funzioni protette virtuali di una classe base non è consentito tramite un puntatore del tipo di classe base all'interno di una classe derivata

3

Considera quanto segue:

#include <iostream>

class Base {
    public:

        void go(){this->doSomething();}

    protected:
        virtual void doSomething(){std::cout << "base";}
};

class DerivedA : public Base {
    protected:
        void doSomething() override {std::cout << "a";}
};

class DerivedB : public Base {
    public:
        Base * basePtr;

        DerivedB()
          :basePtr(new DerivedA())
        {}

    protected:
        void doSomething() override {basePtr->doSomething();} // wont compile
};

int main(int , char *[])
{
   DerivedB b;
   b.go();
}

doSomething () nella sottoclasse DerivedB non verrà compilato, ma non capisco perché questo comportamento esiste! Sto tentando di accedere a una funzione membro virtuale protetta della mia classe base, che avrei pensato sarebbe stata consentita.

link

Nella sezione sull'accesso protetto ai membri, si dice

"È possibile accedere a un membro protetto di una Base di classe 1) dai membri e amici di Base 2) da membri e amici (fino a C ++ 17) di qualsiasi classe derivata da Base, ma solo quando operano su un oggetto di un tipo derivato da Base (incluso questo) "

In base al punto 2, se scrissi nella sottoclasse (DerivedA), ciò sarebbe consentito ma sarei quindi in conflitto con la condizione che accedo a una funzione membro protetta di una classe diversa (che non è un classe base, e anche non compilare). Peggio ancora, se conoscessi il tipo di sottoclasse dell'oggetto derivato, non potrei ancora accedervi anche se lancio nella sua base comune.

Perché questo comportamento è applicato? Presumo che probabilmente sarà un effetto collaterale di consentire l'ereditarietà multipla ecc. Ma non riesco a pensare esattamente a cosa sarebbe. È fastidioso perché ora devo creare un'interfaccia pubblica per qualcosa che è e dovrebbe essere usato solo da classi di base o derivate, che va contro il punto di ereditarietà e modificatori di accesso.

    
posta Andy Forrest 31.03.2017 - 11:04
fonte

1 risposta

2

I am trying to access a virtual protected member function of my base class

Sì, ma stai provando a farlo tramite un altro oggetto basePtr , non questo . E quell'altro oggetto è una Base . In qualche modo confondi classi (tipi) con oggetti (istanze) di quella classe. Non dovresti essere in grado di chiamare una funzione membro protetta di un oggetto Base quando non sei "nello stesso oggetto". E tu non lo sei. Il fatto che tu stia eseguendo il codice all'interno della tua classe derivata non conta qui. Il livello di accesso non viene verificato rispetto all'istanza questa della tua classe derivata, ma all'istanza basePtr a cui desideri accedere.

E va bene così com'è. I progettisti della classe Base non vogliono che la gente chiami doSomething su oggetti di classe Base. Non importa da dove! Questo è ciò che dice la parola protetta. Comunque stanno bene avendo doSomething essere chiamato dall'implementazione di istanze che sono (nel senso di is-a -relationship of inheritance) Basi, cioè da istanze di classi derivate.

    
risposta data 31.03.2017 - 12:13
fonte

Leggi altre domande sui tag