簡體   English   中英

覆蓋函數及其在基類中的調用

[英]Override function and its calls in base class

假設我有以下兩個課程:

class A {
public:
    A() { foo() };
protected:
    virtual void foo();
};

class B : public A {
public:
    B() : super();
private:
    typedef A super;
    void foo();
};

如果我創建一個對象B,是否有一種方法可以強制A的構造函數在調用它時使用重寫的方法?

不,不是。 根據Effective c ++,當對象初始化時,虛擬函數不起作用。 (我用手機寫的,所以這里可能是錯別字)

最好的祝福。

C ++標准,第§12.7節[構造和銷毀]:

成員函數,包括虛函數(10.3),可以在構造或銷毀期間調用(12.6.2)。當從構造函數或析構函數直接或間接調用虛函數時,包括在構造或銷毀類的non時調用-static數據成員,並且調用所應用的對象是正在構造或破壞的對象(稱為x),所調用的函數是構造函數或析構函數的類中的最終重寫器,而不是在派生更高的類中對其進行重寫的對象

當您在A構造函數中時,此時您的對象是A ,調用是否由B構造函數進行無關緊要。

因此,將始終調用A::foo

當從B調用A構造函數時, B尚未構造,因此實際上不會調用A::foo

您可以創建一個函數來創建和初始化您的對象:

struct Base
{
    virtual ~Base();
    virtual void init();
};

struct D : Base
{
    void init() override;
};

D make_D()
{
    D d;
    d.init();
    return d;
}

使用虛擬表可解決對虛擬函數的調用。 任何具有至少一個虛函數的類(及其所有派生類)將各自具有一個虛擬表(在這種情況下,A和B都將包含一個虛表),並且該虛表將按它們被排序的順序包含所有虛函數的地址。宣布。 創建任何此類類的對象時,該對象都包含指向虛擬表的隱藏指針vptr。 因此,首先通過使用vptr轉到虛擬表,然后添加被調用函數的偏移量以獲取函數的地址,然后使用該地址來調用函數來解決虛擬函數的調用。 現在重要的是,vptr是在類的構造函數中初始化的,並且在特定的構造函數中,它將指向該特定類的虛擬表。 在這種情況下,當創建B的對象時,A的構造函數中的vptr(首先調用基類構造函數)將指向A的虛擬表,而當B的構造函數被調用時,vptr僅指向虛擬表。 B的表。這意味着在A的構造函數中,vptr指向A的虛擬表。 因此,當您調用foo()時,編譯器將轉到A的虛擬表,獲取foo()的地址(在本例中為A的foo())並調用此函數。 這就是為什么我們通常說虛擬機制在構造函數內部不起作用的原因。 原因是vptr尚未完全初始化,並且未指向最派生類的vtable。 我希望這有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM