[英]Set derived class field by converting base class pointer
class A
{
public:
int a;
};
class B:public A
{
public:
int b;
void foo()
{
b=a*a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a=new A;
a->a=10;
((B*)a)->foo();
cout<<((B*)a)->b;
}
它適用於b=100
,但我不知道它的工作原理。 b
存放在哪里? 我只是不知道它如何調用谷歌它。
基本上,這里發生的是未定義的行為。 它沒有特別的名字; 最有可能的是它被稱為編程錯誤 。 A
類的內存布局是:
int a;
B
的內存布局是:
int a;
int b;
因此,在您的情況下,您只為a
分配空間,但您很幸運,它后面的空間是空閑的(因此沒有其他信息被覆蓋)並且它沒有在未分配的空間上邊界(否則,可能會發生故障)試圖寫入未分配的頁面)。 所以b
存儲在自由空間中。
簡而言之: 不要依賴這個代碼來工作!
@anderas提供了一個非常好的解釋,為什么行為是未定義的。
以下是該標准的相關條款(n4431,強調我的):
11 ...
如果類型“指向cv1 B的指針”的rvalue指向實際上是D類型對象的子對象的B,則生成的指針指向類型D的封閉對象。 否則,轉換的結果是未定義的 。
[expr.static.cast]
因此,代碼中的強制轉換是未定義的。
以下將有效:
class A
{
public:
int a;
virtual void foo() = 0; // make it polymorphic
};
class B:public A
{
public:
int b;
virtual void foo()
{
b=a*a;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A * a=new B; // create an instance of B
a->a=10;
((B*)a)->foo();
cout<<((B*)a)->b;
// don't forget to delete 'a'
}
行為未定義。 您只能投a
以B*
,如果它是一個指向B
。
不要這樣做。
你甚至不能寫A* a = new B;
接着是(dynamic_cast<B*>(a))->foo();
因為類不是多態類型。
您的代碼將導致2個未定義的行為:
A
的實例轉換為B
。 b
(此變量在內存中不存在)。 這是使用B的實例作為A的指針的pontential實現。
class A
{
public:
void setA(int aToSet)
{
a = aToSet;
}
virtual void foo() = 0;
virtual void getResult() const = 0;
private:
int a;
};
class B : public A
{
public:
void foo() override
{
b = a * a;
}
void getResult() const override
{
return b;
}
private:
int b;
};
int _tmain(int argc, _TCHAR* argv[])
{
A *a = new B();
a->setA(10);
a->foo();
cout << a->getResult();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.