[英]Why does the base class pointer point to the pure virtual method in the base class instead of the overidden method in the derived class?
#include <iostream>
class A
{
public:
virtual ~A() = default;
virtual void foo(void) = 0;
};
class B : public A
{
private:
int x;
public:
B(int a) : x(a) {}
void foo(void) { std::cout << "B: " << x << "\n"; }
};
class Foo
{
private:
A* a_ptr;
public:
Foo (B& x) { a_ptr = &x; }
A* get_ptr(void) { return a_ptr; }
void dummy(void) { std::cout << "Foo: "; std::cout << a_ptr << "\t "<< typeid(*a_ptr).name() << "\n"; a_ptr->foo(); std::cout << "\n"; }
};
int main(void)
{
B b(10);
Foo f(b);
f.dummy();
return 0;
}
如果Foo
的構造函數引用了B
的 object ,那么這個程序將按照我期望的方式執行,即a_ptr->foo()
調用B::foo()
。
但是,如果將構造函數更改為按值接受參數,則a_ptr->foo()
將解析為A::foo()
,並導致pure virtual method called exception
樣品 output(通過引用傳遞:):
Foo: 0x7fffe90a24e0 1B
B: 10
示例 output(按值傳遞):
Foo: 0x7fffc6bbab20 1A
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
我對為什么會發生這種情況有一種模糊的預感,我正在尋找一些可能證明或反駁我的假設的文獻或參考:當通過引用傳遞時,基本 class 指針a_ptr
指向一個生命周期超過過去的實體對a_ptr->foo()
的調用。
但是,當按值傳遞時, a_ptr
指向一個臨時對象,該臨時對象在構造函數退出時會丟失。
我想這與A
的VTABLE
有關,但我不能完全理解它。
是的,你的懷疑是正確的。
當B
object 被傳值到Foo
構造函數中時,就變成了構造函數的局部變量。 構造函數正在保存指向本地 object 的指針,當構造函數退出時,該指針從 scope 中消失。
因此,在Foo::dummy()
中對a_ptr->foo()
的調用實際上是未定義的行為,因為a_ptr
甚至沒有指向有效的 object 開始。 但是,它並沒有真正崩潰,因為A::foo()
沒有使用它的this
指針做任何事情。 它只是指向一個編譯器定義的 function ,它拋出了一個pure virtual method called
,你沒有捕捉到它,所以你的程序終止了。
您通過引用 A* 類型的 a_ptr 分配了臨時 object B。 在構造函數退出時,此臨時 object 已被銷毀。 由於 VTABLE 也被銷毀,稱為 A::foo,它是純虛擬的。 所以你明白了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.