2011-05-11 98 views
4

在C++中,如果基类对象实例化为未定义行为作为基础对象,并随后向下转换为派生对象?向下转换基类型

当然,我会认为它肯定是必须是未定义的行为,因为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? 
} 

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

回答

7

是的,它仍然是未定义的行为,因为您正在向编译器讲述d的实际类型。

参见标准5.2.9/8:类型的“指针CV1 B”,

右边的值,其中B是一个类型,可 转换为类型 “指针的右值如果从“指向 D”到“指向B的指针”的有效 标准转换存在(4.10),则 cv2是与B的派生(第10小节)相同的等级 , ,或者 比cv资格更大,cv1和 B不是虚拟基类D. 空指针值(4.10)为 转换为目标类型的空指针值 。如果 类型“指针CV1 B”点右值进行B ,实际上是类型d的 对象的子对象,将所得 指针指向类型D.的包围对象 否则, 结果演员阵容不确定。

最后两句话说,如果B指向指针实际上不是D派生类中的一部分,该转换是不确定的行为。

1

是的,这是完全未定义的行为。这就是为什么当向下广播时,除非你非常确定,否则你应该支持dynamic_cast

+2

请注意,在这个例子中,因为没有虚函数'dynamic_cast'将不起作用。 – 2011-05-11 17:13:47

4

C++ 03标准, 5.2.9.8勾画出来(重点煤矿):

类型的“指针CV1 B”, 右边的值,其中B是一个类型,可 转换为 类型的右值“指针CV2 D“,其中D是从B派生(第10条)的类别 ,如果存在从”指向 D“到”指向B的指针“的有效 标准转换(4.10),则 cv2与, 或更大的cv-qualification比,cv1, 和B不是虚拟基类 D.空指针值(4。10)将 转换为目标类型的空指针值 。 如果 类型“指针CV1 B”点右值进行B ,实际上是类型d的 对象的子对象,将所得 指针指向类型D.的包围对象 否则,结果 演员阵容未定义。

0

鉴于心理模型我有C++实现中的生成的机器代码我说的术语,如果调用的方法是不虚拟和派生类不引入虚拟方法时基类现在没有,并且多重继承不涉及这个技巧,而且......并且它应该如你所期望的那样工作,如果方法代码确实只访问在基础对象中定义的成员。

但是,这仍然清楚地表明UB在C++中。

+0

那么....它可能适用于一个非常小的情况 - 但它不一定会工作,如果你有多重继承或多个继承层等 – 2011-05-11 18:26:05

+0

是啊...任何不平凡的可能意味着基础对象在派生中不在偏移0处。我编辑了我的回复。 – 6502 2011-05-11 19:24:45