Если у вас есть наследство 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 самого производного объекта.
— в противном случае проверка во время выполнения завершится ошибкой.
Обратите внимание, что стандарт специально требует, чтобы вывод был общедоступным
. Таким образом, 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;
}
person
Alok Save
schedule
26.08.2011
Derived
публично не наследуется отBase
, единственное, что может быть переданоCastToDerived()
, — это указательBase
, потому что не будет никакого способа преобразовать указательDerived
в указательBase
. Таким образом, утверждение никогда не может быть вызвано. - person Praetorian   schedule 26.08.2011Base* Derived::getBase() { return this; }
- person hamstergene   schedule 26.08.2011