考虑:
class base
{
base();
virtual void func();
}
class derived : public base
{
derived();
void func();
void func_d();
int a;
}
main
{
base *b = new base();
sizeof(*b); // Gives 4.
derived * d = static_cast<derived*>(b);
sizeof(*d); // Gives 8- means whole derived obj size..why?
d->func_d();
}
在上面的代码中,我做了一个基指针的向下转换,它指向基对象到派生类指针。我想知道派生指针如何具有整个派生类对象。我可以调用派生类函数(仅在派生类中声明)。我没有在这里得到这个概念。
答案 0 :(得分:20)
使用static_cast
将对象强制转换为某种类型,但实际上并没有产生未定义的行为。 UB的症状差异很大。没有什么可以说UB不能允许成功调用派生成员函数(但是没有什么可以保证它会成功,所以不要指望它。)
以下是使用static_cast
进行向下转换的规则,可在C ++标准的第5.2.9节([expr.static.cast]
)中找到(C ++ 0x措辞):
类型为“指向 cv1
B
的指针”的prvalue,其中B
是类类型,可以转换为类型为“指向的指针的prvalue” cv2D
“,其中D
是从B
派生的类,如果从”指向D
的指针“转换为”指向{{的指针“的有效标准转换1}}“存在, cv2 与 cv1 和B
具有相同的cv资格,或更高的cv资格 既不是B
的虚基类,也不是D
的虚基类的基类。空指针值将转换为目标类型的空指针值。如果“指向 cv1D
的指针”的prvalue指向 到B
实际上是B
类型对象的子对象,结果指针指向封闭对象 类型为D
。否则,演员表的结果是未定义的。
答案 1 :(得分:8)
执行运行时检查的唯一强制转换是dynamic_cast<>()
。如果某个演员阵容在运行时无法运行,则应使用此演员表。
因此从leaf-&gt; root(向上转换)static_cast<>()
进行投射可以正常工作
但是从root-&gt; leaf(向下转换)进行转换是危险的,并且(在我看来)应始终使用dynamic_cast<>()
进行转换,因为它将依赖于运行时信息。成本很低,但总是值得为安全付出代价。
答案 2 :(得分:6)
sizeof
。它既不知道也不关心在运行时,您的基础对象不指向derived
。您试图用运行时变量影响编译时行为,这根本不可能。