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