簡體   English   中英

棘手的多態性和虛函數

[英]Tricky Polymorphism and virtual functions

我有以下代碼。

#include <iostream> 
using namespace std; 

class K { 
public: 
    virtual void add_st(K* n) {
      cout << "add_st (K*) from K\n";
    } 
};

class L: public K { 
public: 
    virtual void add_st(L* a) {
      cout << "add_st (L*) from L\n";
    } 
}; 

int main() { 
    L ob, ob2;
    K  k, *pl = &ob; 
    pl->add_st(&ob2); 
    return 0; 
} 

該程序的輸出為:

add_st (K*) from K

如果我什么都沒錯過的原因是虛函數表。 從層次結構的頂部一直到最低的類生成對象。

但是這段代碼:

#include <iostream> 
using namespace std; 

class K { 
public: 
    virtual void add_st() {
      cout << "add_st (K*) from K\n";
    } 
};

class L: public K { 
public: 
    virtual void add_st() {
      cout << "add_st (L*) from L\n";
    } 
}; 

int main() { 
    L ob, ob2;
    K  k, *pl = &ob; 
    pl->add_st(); 
    return 0; 
} 

將打印

add_st (L*) from L

為什么?

虛函數在參數列表上是不變的,在返回類型上是協變的。

想到這一點的基本方法是,在基類中引入了虛擬成員函數的地方,它定義了一個契約。

例如,給定

struct K
{ 
    virtual K* add_st(K* n);
};

契約是add_st接受任何類型為K對象 (通過指針),並返回類型為K的對象 (按指針)。

這將覆蓋它

struct L : K
{ 
    virtual K* add_st(K* a);
};

因為已清楚地履行了合同,所以:

struct M : K
{ 
    virtual M* add_st(K* a);
};

因為return是M類型的對象,通過繼承它也是K類型的對象; 合同已履行。

但這(問題中的情況)不會被覆蓋

struct N : K
{ 
    virtual K* add_st(N* a);
}; 

因為它不能接受任何類型為K對象,所以只能接受類型均為KN 這也不是:

struct P : K
{ 
    virtual K* add_st(void* a);
};

即使從類型理論的角度來看,逆向參數是兼容的,事實是C ++支持多重繼承,並且上載有時需要指針調整,因此逆向參數類型在實現級別中斷。

他們將創建一個新函數(v表中的新插槽),該函數將重載並隱藏現有函數,而不是覆蓋現有函數。 (正如約翰·史密斯(John Smith)在回答中所說,可以使用using聲明來避免隱藏基本版本)

以下是錯誤,因為簽名相同,但是返回類型不兼容:

struct Q : K
{ 
    virtual void* add_st(K* a);
};

這里的結果可以是任何對象類型,但這還不夠好,合約需要類型為K的對象。 而且它不能覆蓋現有函數,因為參數沒有區別。 因此它只是被拒絕。

有關方差的更多詳細信息,您可能需要閱讀Liskov替代原理

首先,功能簽名包括功能名稱及其參數類型。 在第一個示例中,函數名稱相同,但其參數類型不同。 因此,它們具有不同的簽名。 因此,在第一個示例中,子類中的函數未覆蓋其父類中的函數。

其次還有overload和名稱隱藏的概念。 在您的情況下,第一個示例中的函數定義將隱藏其父函數。 如果將父函數帶入相同的作用域,則子函數將重載父函數,如下所示

class L: public K { 
public: 
    using K::add_st;
    virtual void add_st() {
        cout << "add_st (L*) from L\n";
}; 

暫無
暫無

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

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