C++ override和final關鍵字(詳解版)

2020-07-16 10:04:44
C++ 11 中引入了 override 關鍵字以幫助防止在覆蓋虛擬函式時出現的一些小問題。例如, 在下面的程式中就存在這樣的錯誤。
// This program has a subtle error in the virtual functions.
#include <iostream>
#include <memory>
using namespace std;

class Base
{
    public:
        virtual void functionA(int arg) const{cout << "This is Base::functionA" << endl; }
};

class Derived : public Base
{
    public:
        virtual void functionA(long arg) const{ cout << "This is Derived::functionA" << endl; }
};
int main()
{
    // Base pointer b points to a Derived class object.
    shared_ptr<Base>b = make_shared<Derived>();
    // Call virtual functionA through Base pointer.
    b->functionA(99);
    return 0;
}
程式輸出結果:

This is Base::functionA

在該程式中,Base 類指標 b 指向 Derived 類物件。因為 functionA 是一個虛擬函式,所以一般可以認為 b 對 functionA 的呼叫將選擇 Derived 類的版本。

但是,從程式的輸出結果來看,實際情況並非如此。其原因是這兩個函數有不同的形參型別,所以 Derived 類中的 functionA 不能覆蓋 Base 類中的 functionA。基礎類別中的函數釆用的是 int 型別的引數,而派生類中的函數釆用的則是 long 型別的引數,因此,Derived 類中的 functionA 只不過是過載 Base 類中的 functionA 函數。

要確認派生類中的成員函數覆蓋基礎類別中的虛成員函數,可以在派生類的函數原型(如果函數以內聯方式寫入,則在函數頭)後面加上 override 關鍵字。override 關鍵字告訴編譯器,該函數應覆蓋基礎類別中的函數。如果該函數實際上沒有覆蓋任何函數,則會導致編譯器錯誤。

下面的程式演示了上面程式的修改方法,使得 Derived 類的函數可以真正覆蓋 Base 類的函數。請注意,在該程式中已經將 Derived 類函數的形參修改為 int,並且在函數頭中新增了 override 關鍵字。
//This program demonstrates the use of the override keyword.
#include <iostream>
#include <memory>
using namespace std;

class Base
{
    public:
        virtual void functionA(int arg) const { cout << "This is Base::functionA" << endl;}
};
class Derived : public Base
{
    public:
        virtual void functionA(int arg) const override{ cout << "This is Derived::functionA" << endl; }
};
int main()
{
    // Base pointer b points to a Derived class object.
    shared_ptr<Base>b = make_shared<Derived>();
    // Call virtual functionA through Base pointer.
    b->functionA(99);
    return 0;
}
程式輸出結果:

This is Derived::functionA