C++11新特性之final override識別符號

我是團長發表於2018-12-17

final:

  final修飾符可用於修飾類,放在類名後面,被final修飾符修飾的類不能被繼承。示例程式碼:

// 正確的示範
#include <iostream>

class A
{
public:
    void show_a_info()
    {
        std::cout << "i am class A" << std::endl;
    }
};

class B : public A
{
public:
    void show_b_info()
    {
        std::cout << "i am class B" << std::endl;
    }
};

int main()
{
    B b;
    b.show_a_info();
    b.show_b_info();
    return 0;
}

// 輸出:
// i am class A
// i am class B
// 錯誤的示範
#include <iostream>

class A final
{
public:
    void show_a_info()
    {
        std::cout << "i am class A" << std::endl;
    }
};

class B : public A
{
public:
    void show_b_info()
    {
        std::cout << "i am class B" << std::endl;
    }
};

int main()
{
    B b;
    b.show_a_info();
    b.show_b_info();
    return 0;
}

// 編譯報錯:錯誤    2    error C3246: “B”: 無法從“A”繼承,因為它已被宣告為"final"

  final修飾符還可用於修飾類中的成員函式,但是成員函式必須是虛擬函式,被final修飾符修飾的虛擬函式在子類中不可以被重寫。示例程式碼如下:

// 正確的示範
#include <iostream>

class A
{
public:
    virtual void show_info()
    {
        std::cout << "i am class A" << std::endl;
    }

    virtual void test_final() final
    {
        return;
    }
};

class B : public A
{
public:
    void show_info()    // 可以被重寫
    {
        std::cout << "i am class B" << std::endl;
    }

    void test_final()    // 編譯報錯:A::test_final宣告為final的函式無法被B::test_final重寫
    {
        int count = 0;
        // do_something()
        return;
    }
};

int main()
{
    A *a_ptr = new B();
    a_ptr->show_info();
    return 0;
}

 override:

  在C++11之前,在父類中用virtual宣告一個虛擬函式,在子類中進行重寫時,可以省略virtual修飾符,但是子類中重寫的函式就算省略了virtual修飾符,它依然是個虛擬函式,當我們閱讀程式碼時,子類中的這個函式由於沒有virtual修飾符修飾,我們不去看父類的定義並不會知道在子類中這是一個虛擬函式,為了解決可讀性問題,我們可以在子類中也加上virtual修飾符,但也同樣會帶來如下程式碼中的問題:

class A
{
public:
    virtual void show_info(int x)
    {
        std::cout << "i am class A" << std::endl;
    }
};

class B : public A
{
public:
    virtual void show_info(float x)
    {
        std::cout << "i am class B" << std::endl;
    }
};

  本意是想重寫父類中的show_info(int x)函式,但是寫成了show_info(float x),這樣寫就已經不是重寫了,而是變成了過載。為了解決可讀性及這種重寫被不小心寫成過載的問題,在C++11中當我們想重寫父類的虛擬函式時,可以在子類中重寫的虛擬函式後面加上override修飾符,這樣既標識在子類中這是在重寫父類中的虛擬函式,同時也可以防止重寫被誤寫為過載,因為當子類中對應的函式宣告和父類中不一致時,是編譯不過的,示例如下:

// 正確的示範
#include <iostream>

class A
{
public:
    virtual void show_info(int x)
    {
        std::cout << "i am class A" << std::endl;
    }
};

class B : public A
{
public:
    //virtual void show_info(float a) override    // 錯誤error C3668: “B::show_info”: 包含重寫說明符“override”的方法沒有重寫任何基類方法
    //{
    //    std::cout << "i am class B" << std::endl;
    //}

    virtual void show_info(int a) override        // 正確
    {
        std::cout << "i am class B" << std::endl;
    }
};

 

相關文章