簡體   English   中英

我怎么知道哪個函數會被調用?

[英]How do I know which function will be called?

今天,我在代碼庫中發現了以下令人不安的模棱兩可的情況:

class Base {
public:
    virtual void Irrelevant_Function(void) = 0;

protected:
    C_Container *   Get_Container(void);
};

class A : public Base, public Not_Important {
public:
    inline C_Container *    Get_Container(void);
};

class B : public Base, protected SomethingElse {
public:
    C_Container *   Get_Container(void);
};

很多事情都在調用Get_Container方法,但並不總是調用正確的方法-請注意,這些函數都不是虛擬的。

我需要重命名方法Get_Base_ContainerGet_A_Container等,以消除歧義。 C ++使用什么規則來確定應調用的函數版本? 我想從應該被調用的“已知狀態”開始,然后從那里找出錯誤。

例如,如果我有一個指向Base的指針並調用Get_Container,則假定它只會調用該函數的Base版本。 如果我有一個指向A的指針怎么辦? 指向B的指針呢? 堆上的A或B呢?

謝謝。

這取決於您如何調用該函數。 如果通過A *A &A進行調用,則將調用A::Get_Container() 如果您通過Base *Base & (即使它們指向/引用A )進行調用,那么您將在調用Base::Get_Container()

只要不進行虛擬繼承,就很容易。 如果直接使用對象,則調用該對象的方法。 如果您使用的是指針或引用,則由指針或引用的類型決定方法,而指向的對象的類型則無關緊要。

首先根據對象的靜態類型查找方法 如果那里不是虛擬的,那您就完成了:那就是調用的方法。 動態類型是虛擬方法,dynamic_cast和typeid使用的類型,並且是對象的“實際”類型。 靜態類型是靜態類型系統的工作方式。

A a;                       // Static type and dynamic type are identical.
Base &a_base = a;          // Static type is Base; dynamic type is A.

a.Get_Contaienr();         // Calls A::Get_Container.
a_base.Get_Container();    // Calls Base::Get_Container.

B *pb = new B();           // Static type and dynamic type of *pb (the pointed-to
                           // object) are identical.
Base *pb_base = pb;        // Static type is Base; dynamic type is B.

pb->Get_Container();       // Calls B::Get_Container.
pb_base->Get_Container();  // Calls Base::Get_Container.

上面我假設受保護的Base :: Get_Container方法是可訪問的,否則這些將是編譯錯誤。

在此需要注意的其他幾點:

名稱查找在單個作用域中進行; 例如,當在靜態類型為'B'的對象上調用該方法時,編譯器將考慮接口'B'以確定是否存在有效的匹配項。 如果不存在,則僅查看Base的接口以找到匹配項。 這就是為什么從編譯器的角度來看,沒有歧義並且可以解決調用的原因。 如果您的真實代碼有重載等,則可能是一個問題。

其次,通常會忘記“ protected”關鍵字在類而非對象級別適用。 因此,例如:

class Base {
protected:
    C_Container *   Get_Container(void);
};

class B : public Base{
public:
    C_Container *   Get_Container(void)
    {
        B b;
        // Call the 'protected' base class method on another object.
        return b.Base::Get_Container();
    }
};

暫無
暫無

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

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