重寫、重載和重定義的區別



重寫(override)


首先,重寫是指派生類的方法覆蓋基類的方法,要求方法名、方法的參數都相同。重寫是C++中實現多態這個特性基礎。重寫又稱為覆蓋,是指派生類函數覆蓋基類函數,與重定義不同,重寫要求被重寫的基類函數為虛函數。
例如下面的代碼:

class Base{
public:
    virtual int Total(int unit_price, int num) = 0;
};
class Derived :public Base{
public:
    virtual int Total(int unit_price, int num)
    {
        cout << "test" << endl;
        return 0;
    }
};
class Child :public Derived{
public:
    int Total(int unit_price, int num)
    {
        //
        return unit_price*num;
    }
};

總結一下,重寫是指派生類重新定義了基類的虛函數,基類函數必須有virtual關鍵字修飾,不能有static關鍵字;返回值類型必須是相同的,或者是協變的;此外重寫函數的訪問修飾符可以不同。
注意:一般重寫要求函數具有完全相同的入參,否則就會提示錯誤,而這個規則對於協變而言則有所放松。覆蓋的返回值不區分基類或者派生類,如下代碼:

class Base{
public:
    virtual int Total(int unit_price, int num)
    {
        cout << "Base" << endl;
        return 0;
    }
};
class Derived :public Base{
public:
    virtual int Total(int unit_price, int num)
    {
        cout << "test" << endl;
        return 1;
    }
};
//協變
class Father{
public:
    virtual const Base& getClass() = 0;
};
class Child{
    virtual const Derived& getClass()
    {
        Derived ret;
        return ret;
    }
};

在上面協變的例子中,要求Base和Derived兩個類必須在使用前被完整的定義。
協變返回類型的優勢在於,若是我們使用Father,就能獲得一個抽象的Base,如果我們正在處理Child,就會獲得一個Derived。協變的返回機制將我們從這樣一種處境中解脫出來:不得不使用易於出錯的轉換操作來“重新”提供類型信息,而這種信息是一開始就不應該丟掉的。


重載(overload)


然后是重載(overload),重載是應用於相同作用域之內的同名函數,由於參數列表不同而產生的不同的實現方法。此處提到的作用域有:全局作用域、局部作用域以及類作用域,當在同一個作用域內的時候同名的函數或者稱之為方法,由於參數列表的不同,而獲得的不同的函數。

int Sum(int a, int b);
int Sum(int a, int b, int c);
int Sum(float a, float b);

重載是一種語言特性,是一種語法規則,與多態無關,與面向對象無關。


重定義


重定義則是經常出現在基類和派生類之間,歸結起來有如下的特點:
1)不在同一個作用域,主要是指類作用域,分別位於基類和派生類之中;
2)函數名稱相同,但是返回值可以不同;
3)參數不同時,無論有沒有virtual關鍵字,基類的函數都會被隱藏;參數相同時,但是基類函數沒有關鍵字virtual,此時基類函數被隱藏。
例如:

class Base{
public:
    virtual double Total(double a, double b)
    {
        return a + b;
    }
    void Print()
    {
        cout << "Base" << endl;
    }
    int Sum(int a, int b);

private:
    //
};
class Derived :public Base{
public:
    virtual double Total(double a, double b, double c)
    {
        return a + b + c;
    }
    void Print()
    {
        cout << "Derived" << endl;
    }
    int Sum(int a, int b, int c);
};

在運行Derived的實例的時候可以很容易的發現,基類中Sum函數被隱藏了。因此重定義又稱為隱藏,是指派生類的函數屏蔽了與其同名的基類函數。

int _tmain(int argc, _TCHAR* argv[])
{
    Derived test;
    test.Print();
    Derived test_b;
    Base *p;
    p = new Derived;
    p->Print();
    Base *p_2;
    p_2 = &test_b;
    p_2->Print();
    delete p;
    system("pause");
    return 0;
}

例如上面的類,我們在如上調用的時候得到了下面的輸出:
這里寫圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM