2012-07-05 58 views
1

我有一个基类(car)和类继承的基类(honda):如何正确投射我的派生类?

class car 
{ 
    virtual void polymorphic_class() 
    { } 
}; 

class honda : public car 
{ }; 


当我使用下面的代码,我投我班得到一个空指针:

list<car> cars; 
honda h; 
cars.push_back(h); 
honda* h_ptr = dynamic_cast<honda*>(&cars.back()); 
// h_ptr is NULL 

为什么?我如何正确投射我的物体?

+1

没有办法正确做这个演员。你的清单是“汽车”列表。它没有(也不能)包含'honda's。 – 2012-07-05 11:32:04

回答

2

多态性适用于指针和引用,而不适用于对象实例。

在这种情况下,您的列表包含类型为car的对象,而不是任何派生类型。当您插入honda时,它将复制car部分并忽略其余部分;这有时被称为切片

对于多态,你可以使用指针列表:

list<car*> cars {new honda}; 
honda * h_ptr = dynamic_cast<honda*>(cars.back()); // should be a valid pointer 

注:如果您分配使用new在我的例子,记得无论是delete它们,或存储智能指针(如std::unique_ptr<car>),而比原始指针。您还需要一个虚拟析构函数才能使用基类指针删除对象。

您可以通过使基类抽象为来避免切片问题;如果它包含纯虚函数,那么你就不能仅实例化派生类型类型的对象,覆盖这些功能:如果你不真正想要的抽象接口

class car 
{ 
    virtual ~car() {} 
    virtual void do_something() = 0; 
}; 

class honda : public car 
{ 
    void do_something() {} 
}; 

(例如,如果你只访问派生类功能使用dynamic_cast而不是通过虚函数),那么你可以使析构函数变为纯虚拟的;那么派生类将不必显式地覆盖任何东西。基类的析构函数仍然必须落实,由于语言的怪癖,即实现必须是类定义之外:

class car 
{ 
    virtual ~car() = 0; 
}; 
inline car::~car() {} 

class honda : public car {}; 

这是一个有点不寻常的做法,因为多态性通过虚拟函数通常更有效更方便。

4

这不起作用的原因是对象切片cars中的对象不再是honda s,而只是汽车。

你需要指针或智能指针的载体:

list<car*> cars; 
honda h; 
cars.push_back(&h); 
honda* h_ptr = dynamic_cast<honda*>(cars.back()); 

其实我更改了设计,car抽象(纯虚析构函数或东西)。这样你也会得到一个编译错误。

+0

无论如何,我没有编码错误。 – Nick 2012-07-05 11:35:26

+3

@尼克但你不喜欢吗? – 2012-07-05 11:35:42

+0

@尼克我知道你现在没有得到一个,但如果你有一个,你可以在早期发现这些问题。 – 2012-07-05 11:36:10

0

试试这个

list<car*> cars; 
honda *h = new honda(); 
cars.push_back(h); 
honda* h_ptr = dynamic_cast<honda*>(cars.back()); 

这工作。