Возможно ли то, что я пытаюсь достичь. Это проблема:
class Content{};
class Content1 : public Content{};
class Content1_1 : public Content1{};
class Content1_2 : public Content1{};
class Content2 : public Content{};
class Content2_1 : public Content2{};
class Content2_2 : public Content2{};
class Container{
public:
Content* c;
};
Можно ли определить, является ли указатель Container
класс указывает на объект Content1
или объект класса, производного от Content1
?
Благодарю.
РЕДАКТИРОВАТЬ:
Если я посмотрю тип указателя в container
класс, это рассматривается как content
типа, хотя это может быть на самом деле content1
или же content2
тип, так что dynamic_cast не работает.
class content{};
class content1 : public content{};
class content2 : public content{};
class container{
public:
content* c;
};
int main(void)
{
container* x = new container;
x->c = new content2;
if( dynamic_cast<content1*>((content1*)x->c) == NULL){
//This doesn't fail, eventhough 'content1' and 'content2' shouldn't be compatible.
//This means that every class, derived from 'content' will be treated as 'content1' when using dynamic_cast.
}
return 0;
}
Если ваши типы полиморфны (то есть если у них есть хотя бы один virtual
функция), вы можете использовать dynamic_cast<>
, Результат dynamic_cast<>
будет нулевым указателем (т.е. nullptr
для C ++ 11, NULL
для C ++ 03) в случае, если указанный объект фактически не является экземпляром указанного класса или его производного класса:
Container cont;
Content1* pContent1 = dynamic_cast<Content1*>(cont.c);
if (pContent1 != nullptr)
{
// cont.c points to an instance of Content1
// or a class derived from Content1
}
Обычной практикой является сделать деструктор вашего базового класса виртуального, так что объекты класса, производного от вашего базового класса могут быть delete
через указатель базового класса (если деструктор не virtual
попытка сделать это приводит к неопределенному поведению):
class Content //Abstract.
{
public:
virtual ~Content() { }
// ^^^^^^^
};
Да использовать dynamic_cast
— http://www.cplusplus.com/doc/tutorial/typecasting/
Это даст вам RTTI — Информация о типе времени выполнения.
Content1 * p = dynamic_cast<Content1 *>(c);
если p не NULL, то c указывает на объект, который является Content1 или является производным от Content1.
Однако ваша классовая иерархия должна быть полиморфной. Так как ваш класс Content
является абстрактным (я предполагаю, что у вас есть чисто виртуальная функция в Content), вся ваша иерархия автоматически становится полиморфной.
Если вам нужно знать точный тип времени исполнения полиморфного класса, вам следует переосмыслить свой дизайн. Обычно лучше либо хранить объекты разных типов в разных контейнерах (дополнительно, либо вместо одного центрального контейнера), либо добавлять виртуальную функцию к каждому из производных классов, которая выполняет действие, при котором вам придется различать типы.
В FAQ C ++ есть запись, которая может вам помочь: У меня есть гетерогенный список объектов, и мой код должен делать специфичные для класса вещи с объектами. Кажется, что это должно использовать динамическое связывание, но не может понять это. Что я должен делать?
Если вы хотите увидеть, если Content*
указывает на объект класса, производного от Content2
класс просто бросил его dynamic_cast
и посмотреть.
Это работает:
#include <iostream>
#include <typeinfo>
using namespace std;
class Content{public: virtual ~Content(){}};
class Content1 : public Content{public: virtual ~Content1(){}};
class Content1_1 : public Content1{public: virtual ~Content1_1(){}};
class Content1_2 : public Content1{public: virtual ~Content1_2(){}};
class Content2 : public Content{public: virtual ~Content2(){}};
class Content2_1 : public Content2{public: virtual ~Content2_1(){}};
class Content2_2 : public Content2{public: virtual ~Content2_2(){}};
class Container{
public:
Content* c;
};
int main()
{
Content* cnt=new Content2_1;
if(dynamic_cast<Content2_1*>(cnt))
cout << "True" << endl;
return 0;
}