С++: "... не является полиморфным типом" при использовании boost:: dynamic_pointer_cast
Почему я получаю следующую ошибку для следующего кода?
1>C:\Libs\boost_1_44\boost/smart_ptr/shared_ptr.hpp(259): error C2683: 'dynamic_cast' : 'my_namespace::A' is not a polymorphic type
1> D:\[location]\[header_filename].h(35) : see declaration of 'my_namespace::A'
1> C:\Libs\boost_1_44\boost/smart_ptr/shared_ptr.hpp(522) : see reference to function template instantiation 'boost::shared_ptr<T>::shared_ptr<my_namespace::A>(const boost::shared_ptr<my_namespace::A> &,boost::detail::dynamic_cast_tag)' being compiled
1> with
1> [
1> T=my_namespace::B
1> ]
1> [location]\[source_filename].cpp(217) : see reference to function template instantiation 'boost::shared_ptr<T> boost::dynamic_pointer_cast<my_namespace::B,striker::A>(const boost::shared_ptr<my_namespace::A> &)' being compiled
1> with
1> [
1> T=my_namespace::B
1> ]
1>C:\Libs\boost_1_44\boost/smart_ptr/shared_ptr.hpp(260): fatal error C1903: unable to recover from previous error(s); stopping compilation
Код С++ имеет более или менее следующее значение:
#include <list>
#include "boost/pointer_cast.hpp"
#include "boost/shared_ptr.hpp"
struct A
{
public:
A(const MyEnum an_enum_, const int an_int_) :
an_enum(an_enum_),
an_int(an_int_)
{}
const MyEnum an_enum;
const int an_int;
};
struct B : public A {
public:
B(const int some_int_, const MyStruct &a_struct_) :
A(ENUM_OPTION_A, an_int_),
a_struct(a_struct_)
{}
const MyStruct a_struct;
};
// Ussage in some function:
// ...
boost::shared_ptr<A> a_ptr = boost::shared_ptr<A>( new B() );
std::list<boost::shared_ptr<A>> a_list;
a_list.push_back(a_ptr);
// ...
boost::shared_ptr<A> a_ptr2 = a_list.front();
boost::shared_ptr<B> b_ptr = boost::dynamic_pointer_cast<B>(a_ptr2); // <-- error here
// ...
Ответы
Ответ 1
dynamic_cast
работает ТОЛЬКО с полиморфным классом. А класс polymorphic
- это то, что имеет хотя бы одну функцию virtual
, даже если это деструктор.
//polymorphic classes
struct A
{
virtual ~A(); //even virtual destructor makes a class polymorphic!
};
struct B : A
{
void f();
};
//non-polymorphic classes
struct C
{
~C(); //not virtual
};
struct D : C
{
void f(); //not virtual either
};
В приведенном выше коде A
и B
являются полиморфными классами, но C
и D
не являются.
A *pA = new B();
B *pB = dynamic_cast<B*>(pA); //okay
C *pC = new D();
D *pD = dynamic_cast<D*>(pC); //error - not polymorphic class
Обратите внимание, что в dynamic_cast
для компиляции должен использоваться только тип источника. Если пункт назначения не является полиморфным, то dynamic_cast
вернет нулевой указатель.
D *pD = dynamic_cast<D*>(pA); //okay - source (pA) is polymorphic
if ( pD )
cout << "pD is not null" ;
else
cout << "pD is null";
Вывод:
pD is null
Демо-версия онлайн: http://www.ideone.com/Yesxc
Ответ 2
'dynamic_cast' : 'my_namespace::A' is not a polymorphic type
, потому что он не определяет или не наследует одну функцию virtual
. Просто добавьте виртуальный деструктор, и все будет в порядке.
dynamic_cast
работает только для таких "полиморфных" типов.
Ответ 3
struct A
не имеет виртуальных методов (даже деструктор), поэтому вы не можете dynamic_cast
от A*
- только указатели на типы с хотя бы одной виртуальной функцией-членом могут использоваться dynamic_cast
on. boost::dynamic_pointer_cast
выполняет dynamic_cast
внутри, подчиняется тем же требованиям.