向下转型基础类型

时间:2011-05-11 16:59:32

标签: c++ inheritance

在C ++中,如果基类对象被实例化作为基础对象,并且随后向下转换为派生对象,那么它是未定义行为吗?

当然,我认为肯定必须是未定义的行为,因为Derived类对象可能具有基类不具有的成员变量。因此,如果将类实例化为基础对象,则这些变量实际上不存在,这意味着通过Derived类指针访问它们必须导致未定义的行为。

但是,如果Derived类只提供额外的成员函数,但不包含任何其他成员数据,该怎么办?例如:

class Base
{
    public:
    int x;
};

class Derived : public Base
{
    public:
    void foo();    
};

int main()
{
    Base b;
    Derived* d = static_cast<Derived*>(&b);
    d->foo(); // <--- Is this undefined behavior?
}

此程序是否会导致未定义的行为?

4 个答案:

答案 0 :(得分:7)

是的,它仍然是未定义的行为,因为你对编译器说谎d的实际类型。

见标准5.2.9 / 8:

  

“指向cv1 B的指针”类型的右值,   其中B是类类型,可以   转换为类型的右值   “指向cv2 D的指针”,其中D是一个类   如果有效,则从B派生(第10条)   标准转换从“指针到   D“到”指向B的指针“存在(4.10),   cv2与cvqualification相同,或   比cv1更高的资格认证   B不是D的虚拟基类。   空指针值(4.10)是   转换为空指针值   目的地类型。如果是左值   键入“指向cv1 B的指针”指向B   这实际上是一个子对象   D型对象,由此产生   指针指向封闭对象   D型。否则,结果   演员阵容未定义。

最后两句话说如果指针指向的B实际上不是D派生类的一部分,那么强制转换是未定义的行为。

答案 1 :(得分:4)

C ++ 03标准,参与。 5.2.9.8列出(强调我的):

  

“指向cv1 B的指针”类型的右值,   其中B是类类型,可以   转换为类型的右值   “指向cv2 D的指针”,其中D是一个类   如果有效,则从B派生(第10条)   标准转换从“指针到   D“到”指向B的指针“存在(4.10),   cv2与cv资格相同,   或者更高的cv资格,比cv1,   和B不是虚拟基类   D.空指针值(4.10)是   转换为空指针值   目的地类型。 如果是rvalue   键入“指向cv1 B的指针”指向B   这实际上是一个子对象   D型对象,由此产生   指针指向封闭对象   D型。否则,结果   演员阵容未定义。

答案 2 :(得分:1)

是的,这是完全未定义的行为。这就是为什么在向下倾斜时你应该支持dynamic_cast,除非你非常肯定。

答案 3 :(得分:0)

鉴于我在生成的机器代码方面的C ++实现的心智模型,我会说如果调用的方法不是虚拟的,并且派生类在基类没有时引入虚方法,并且多重继承是如果方法代码确实只访问在基础对象中定义的成员,那么它应该按照您的预期工作。

然而,这仍然是C ++中的UB。