在 C++ 中使用“static_cast”进行向下转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6322949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Downcasting using the 'static_cast' in C++
提问by G Mann
Consider:
考虑:
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();
}
In the above code I did downcasting of a base pointer which points to base object to derived class pointer. I am wondering how the derived pointer has the whole derived class object. I can call the derived class function (declared in derived class only). I did not get the concept here.
在上面的代码中,我将指向基对象的基指针向下转换为派生类指针。我想知道派生指针如何拥有整个派生类对象。我可以调用派生类函数(仅在派生类中声明)。我在这里没有得到这个概念。
回答by Ben Voigt
Using static_cast
to cast an object to a type it doesn't actually have yields undefined behavior. The symptoms of UB vary widely. There's nothing that says UB can't allow the derived member function to be called successfully (but there's nothing that guarantees that it will, so don't count on it).
使用static_cast
将对象强制转换为它实际上没有的类型会产生未定义的行为。UB 的症状差异很大。没有什么说 UB 不能允许成功调用派生成员函数(但没有什么可以保证它会成功,所以不要指望它)。
Here is the rule for downcasting using static_cast
, found in section 5.2.9 ([expr.static.cast]
) of the C++ standard (C++0x wording):
以下是使用C++ 标准(C++0x 措辞)的static_cast
第 5.2.9 ( [expr.static.cast]
)节中的向下转换规则:
A prvalue of type "pointer to cv1
B
", whereB
is a class type, can be converted to a prvalue of type "pointer to cv2D
", whereD
is a class derived fromB
, if a valid standard conversion from "pointer toD
" to "pointer toB
" exists, cv2is the same cv-qualification as, or greater cv-qualification than, cv1, andB
is neither a virtual base class ofD
nor a base class of a virtual base class ofD
. The null pointer value is converted to the null pointer value of the destination type. If the prvalue of type "pointer to cv1B
" points to aB
that is actually a subobject of an object of typeD
, the resulting pointer points to the enclosing object of typeD
. Otherwise, the result of the cast is undefined.
“指向cv1 的指针
B
”类型的纯右值,其中B
是类类型,可以转换为“指向cv2 的指针D
”类型的纯右值,其中D
是派生自 的类B
,如果从“指向D
”的有效标准转换为“指针”为了B
“存在,cv2是与cv1相同的 cv 限定,或比cv1更大的 cv 限定,并且B
既不是 的虚拟基类,D
也不是 的虚拟基类的基类D
。空指针值转换为目标类型的空指针值。如果类型为“指向cv1 的指针B
”的纯右值B
D
,结果指针指向类型为 的封闭对象D
。否则,转换的结果是未定义的。
回答by Martin York
The only cast that does runtime checking is dynamic_cast<>()
. If there is any possibility that a cast will not work at runtime then this cast should be used.
进行运行时检查的唯一强制转换是dynamic_cast<>()
. 如果有可能在运行时强制转换不起作用,则应使用此强制转换。
Thus casting from leaf->root (up casting) static_cast<>()
works fine.
But casting from root->leaf (down casting) is dangerous and (in my opinion) should always be done with dynamic_cast<>()
as there will be dependencies on run-time information. The cost is slight, but always worth paying for safety.
因此,从叶-> 根(向上铸造)铸造static_cast<>()
工作正常。
但是从 root->leaf 转换(向下转换)是危险的,(在我看来)应该总是这样做,dynamic_cast<>()
因为这会依赖于运行时信息。成本很小,但总是值得为安全付出代价。
回答by Puppy
sizeof
exists at compile-time. It neither knows nor cares that at run-time, your base object doesn't point to a derived
. You are attempting to influence compile-time behaviour with a run-time variable, which is fundamentally impossible.
sizeof
编译时存在。它既不知道也不关心在运行时,您的基础对象不指向derived
. 您正在尝试使用运行时变量影响编译时行为,这从根本上是不可能的。