![](/img/trans.png)
[英]When is a `static_cast<Base*>(static_cast<void*>(derived))` from a pointer to a derived class valid?
[英]Can static_cast be done from base class to derived class if derived class contains additional methods and members?
假设我们有A类和B类如下:
class A
{
private:
int a;
public:
void seta(int a_)
{
a=a_;
}
int geta()
{
return a;
}
};
class B: public A
{
private:
int b;
public:
int getb()
{
return b;
}
void setb()
{
b=geta()+1;
}
};
并假设我在函数中创建了这样的代码:
A* a=new A();
a->seta(5);
B* b=static_cast<B*>(a);
b->setb();
cout<<b->getb()<<" and "<<b->geta()<<endl;
这段代码编译并运行,但它让我困惑为什么? 如果a
是指向A
类的指针,并且在分配期间只保留了class A
成员的内存(在运行时),为什么在静态转换之后看起来这个对象实际上是class B
实例。 这是安全的操作吗?
[expr.static.cast] / 11 ,强调我的:
类型为“指向cv1
B
指针”的prvalue,其中B
是类类型,可以转换为类型为“指向cv2D
指针”的prvalue,其中D
是从B
派生的类(第10条),如果cv2是与cv1相同的cv资格,或更高的cv资格。 如果B
是虚拟基类的D
或基类的虚拟基类中的D
,或如果从“指针没有有效的标准转换D
”到“指针B
”的存在(4.11),是形成不良的程序。 空指针值(4.11)将转换为目标类型的空指针值。 如果类型的prvalue“指针CV1B
”指向一个B
实际上是类型的对象的子对象D
,将所得指针指向类型的包围对象D
。 否则,行为未定义。
这不是一件安全的事情。 以下代码说明了原因
#include <iostream>
using namespace std;
class A
{
private:
int a;
public:
void seta(int a_) {
a=a_;
cout << "seta to: " << a << endl;
}
int geta() {
return a;
}
};
class B: public A
{
private:
int b;
public:
int getb() {
return b;
}
void setb() {
b=geta()+1;
cout << "setb to: " << b << endl;
}
};
int main() {
A as[2];
A* a1=as;
A* a2=&as[1];
a1->seta(5);
a2->seta(4);
cout << "a1: "
<< a1->geta()
<< endl;
cout << "a2: "
<< a2->geta()
<< endl;
B* b=static_cast<B*>(a1);
b->setb();
a2->seta(3);
cout << "b->geta(): "
<< b->geta()
<<" and b->getb(): "
<< b->getb()
<< endl;
size_t sizeofa(sizeof(A));
cout << "sizeofa: "
<< sizeofa
<< endl;
size_t sizeofb(sizeof(B));
cout << "sizeofb: "
<< sizeofb
<< endl;
}
输出是
seta to: 5
seta to: 4
a1: 5
a2: 4
setb to: 6
seta to: 3
b->geta(): 5 and b->getb(): 3
sizeofa: 4
sizeofb: 8
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.