Если у вас есть Protected
или Private
Наследование, вы не можете сделать:
Base *ptr = new Derived();
и вы не можете,
Derived *ptr1 = new Derived();
Base *ptr = ptr1;
Это потому, что Base
является недоступной базой Derived
Поскольку вы не можете иметь указатель класса Base
, указывающий на объект класса Derived
, эта проверка выглядит избыточной.
EDIT:
Даже если вы не можете напрямую назначить объект класса Derived
указателю класса Base
, это может произойти и другими способами, например: если функция класса Derived
возвращает указатель класса Base
.
Короче говоря, указатель класса Base
может указывать на объект класса Derived
, даже если деривация равна protected
или private
.
Учитывая вышеизложенное,
Согласно стандарту C ++:
5.2.7.8:
Проверка времени выполнения логически выполняется следующим образом:
- Если в самом производном объекте, на который указывает (ссылается) v, v указывает (ссылается) на подобъект общедоступного базового класса объекта T, и если только один объект типа T получен из указанного подобъекта (ссылается на v), результатом является указатель (ссылка на lvalue) на этот объект T.
- В противном случае, если v указывает (ссылается) на подобъект общедоступного базового класса самого производного объекта, а тип самого производного объекта имеет базовый класс типа T, который является однозначным и public
, результатом является указатель (ссылающийся на lvalue) на подобъект T самого производного объекта .
- В противном случае проверка во время выполнения завершится неудачно.
Обратите внимание, что стандарт специально налагает требование деривации: Public.
Таким образом, dynamic_cast
обнаружит обработку приведения как неподходящего приведения, если деривация равна protected
или private
, и вернет NULL
(так как вы используете указатель), и будет вызван assert
.
Так что да, код очень правильный. И это действительно делает то, что говорит комментарий
Этот образец демонстрирует, что он работает согласно комментариям:
#include<iostream>
class Base
{
public:
virtual bool IsDerived() const { return false; }
};
class Derived : protected Base
{
public:
bool IsDerived() const { return true; }
Base* getBase() { return this; }
};
Derived* CastToDerived( Base* base )
{
// private and protected inheritance from Derived is prohibited
Derived* derived = dynamic_cast<Derived*>(base);
if( derived == 0 )
{
std::cout<< "!base->IsDerived()";
}
return derived;
}
int main()
{
Derived *ptr3 = new Derived();
Base *ptr = ptr3->getBase();
Derived *ptr2 = CastToDerived(ptr);
return 0;
}