[英]Overriding function in C++ doesn't work
#include <cstdio>
using namespace std;
class A {
public:
virtual void func() { printf("A::func()"); }
};
class B : public A {
public:
virtual void func() { printf("B::func()"); }
};
int main() {
A a = *(A *)new B();
a.func();
}
這個問題很簡單:為什么a->func()
調用類的函數A
即使a
包含B類的對象?
A a = *(A *)new B();
a.func();
以下是此代碼中一步一步發生的情況:
new B()
:在免費商店中分配類型B的新對象,從而生成其地址 (A*)
:對象的地址被強制轉換為A*
,因此我們有一個類型為A*
的指針實際指向類型為B的對象,該對象是有效的。 一切都好。 A a
:這里問題就出現了。 在堆棧上創建類型A的新本地對象 ,並使用復制構造函數A::A(const A&)
構造,第一個參數是之前創建的對象。 new
分配在免費存儲上的。 a.func()
- 在A類的(本地)對象上調用該方法。 如果您將代碼更改為:
A& a = *( A*) new B();
a.func();
然后只構造一個對象,它的指針將轉換為A*
類型A*
指針,然后解除引用,並用該地址初始化一個新的引用 。 然后,虛函數的調用將動態解析為B::func()
。
但請記住,您仍需要釋放該對象,因為它已分配給new
:
delete &a;
順便說一句,如果A有一個虛擬的析構函數,那將是正確的,這需要B ::〜B()(幸運的是這里是空的,但在一般情況下它不需要)也將是調用。 如果A沒有虛擬析構函數,那么您需要通過以下方式釋放它:
delete (B*)&a;
如果您想使用指針,那么與引用相同。 碼:
A* a = new B(); // actually you don't need an explicit cast here.
a->func();
delete (B*)a; // or just delete a; if A has a virtual destructor.
現在您已修改了代碼段,問題很明顯。 多態性(即虛函數)僅通過指針和引用調用。 你沒有這些。 A a = XXX
不包含類型B
的對象,它包含類型A
的對象。 您通過執行指針轉換和取消引用來“切掉”對象的B
度。
如果你做A *a = new B();
,那么你將得到預期的行為。
這可能就是這個伎倆。
A &a = *(A *)new B();
a.func();
要么
A *a = new B();
a->func();
虛擬調度僅適用於指針或引用類型:
#include <cstdio>
using namespace std;
class A {
public:
virtual void func() { printf("A::func()"); }
};
class B : public A {
public:
virtual void func() { printf("B::func()"); }
};
int main() {
A* a = new B();
a->func();
}
問題是使用A a = *(A *)new B()將B與A一起推向A:
您可以通過刪除*(A *)將其更改為(A * a = new B();)來修復它,但我會更進一步,因為您的變量名稱不適合B的實例化。
它應該是
B *b = new B();
b->func();
因為在將動態分配的對象復制到類型A
對象a
(這也給了您內存泄漏)時執行了切片。
a
應該是引用( A&
),或者只是保留指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.