[英]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.