91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++11中的override有什么用

發布時間:2022-03-21 09:10:49 來源:億速云 閱讀:182 作者:小新 欄目:開發技術

這篇文章主要介紹了C++11中的override有什么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

1 公有繼承

公有繼承包含兩部分:一是"函數接口" (interface),二是"函數實現" (implementation)

如 Shape 類中,三個成員函數,對應三種繼承方式:

class Shape {
public:
    virtual void Draw() const = 0;    // 1) 純虛函數
    virtual void Error(const string& msg);  // 2) 普通虛函數
    int ObjectID() const;  // 3) 非虛函數
};
class Rectangle: public Shape { ... };
class Ellipse: public Shape { ... };  

1.1 純虛函數 (pure virtual)

Shape *ps1 = new Rectangle;
ps1->Draw(); // calls Rectangle::Draw
Shape *ps2 = new Ellipse;
ps2->Draw(); // calls Ellipse::Draw  

純虛函數,繼承的是基類中,成員函數的接口,且要在派生類中,重寫成員函數的實現

調用基類的 Draw(),須加 類作用域操作符 ::

ps1->Shape::Draw(); // calls Shape::draw  

1.2 普通虛函數

普通虛函數,會在基類中,定義一個缺省的實現 (default implementation),表示繼承的是基類成員函數接口和缺省實現,由派生類選擇是否重寫該函數。

實際上,允許普通虛函數 同時繼承接口和缺省實現是危險的。如下, ModelA 和 ModelB 是 Airplane 的兩種飛機類型,且二者的飛行方式完全相同

class Airplane {
public:
    virtual void Fly(const string& destination);
};
class ModelA: public Airplane { ... };
class ModelB: public Airplane { ... }; 

這是典型的面向對象設計,兩個類共享一個特性 -- Fly,則 Fly 可在基類中實現,并由兩個派生類繼承之

現增加另一個飛機型號 ModelC,其飛行方式與 ModelA,ModelB 不相同,如果不小心忘記在 ModelC 中重寫新的 Fly 函數

class ModelC: public Airplane {
    ... // no fly function is declared
}; 

則調用 ModelC 中的 fly 函數,就是調用 Airplane::Fly,但是 ModelC 的飛行方式和缺省的并不相同

Airplane *pa = new ModelC;
pa->Fly(Qingdao); // calls Airplane::fly!  

即前面所說的,普通虛函數同時繼承接口和缺省實現是危險的,最好是基類中實現缺省行為 (behavior),但只有在派生類要求時才提供該缺省行為

1.2.1 方法一

一種方法是 純虛函數 + 缺省實現,因為是純虛函數,所以只有接口被繼承,其缺省的實現不會被繼承。派生類要想使用該缺省的實現,必須顯式的調用

class Airplane {
public:
    virtual void Fly(const string& destination) = 0;
};
 
void Airplane::Fly(const string& destination)
{
    // a pure virtual function default code for flying an airplane to the given destination
}
class ModelA: public Airplane {
    virtual void Fly(const string& destination) { Airplane::Fly(destination); }
};  

這樣在派生類 ModelC 中,即使一不小心忘記重寫 Fly 函數,也不會調用 Airplane 的缺省實現

class ModelC: public Airplane {
public:
    virtual void Fly(const string& destination);
};
 
void ModelC::Fly(const string& destination)
{
    // code for flying a ModelC airplane to the given destination
}  
1.2.2 方法二

可以看到,上面問題的關鍵就在于,一不小心在派生類 ModelC 中忘記重寫 fly 函數,C++11 中使用關鍵字 override,可以避免這樣的“一不小心”

1.3 非虛函數

非虛成員函數沒有 virtual 關鍵字,表示派生類不但繼承了接口,而且繼承了一個強制實現 (mandatory implementation)

既然繼承了一個強制的實現,則在派生類中,無須重新定義 (redefine) 繼承自基類的成員函數,如下:

使用指針調用 ObjectID 函數,則都是調用的 Shape::ObjectID()

Rectangel rc; // rc is an object of type Rectangle
Shape *pB = &rc; // get pointer to rc
pB->ObjectID(); // call ObjectID() through pointer
Rectangle *pD = &rc; // get pointer to rc
pD->ObjectID(); // call ObjectID() through pointer 

如果在派生類中重新定義了繼承自基類的成員函數 ObjectID 呢?

class Rectangel : public Shape {
public:
    int ObjectID() const; // hides Shape::ObjectID
};
pB->ObjectID(); // calls Shape::ObjectID()
pD->ObjectID(); // calls Rectagle::ObjectID()  

此時,派生類中重新定義的成員函數會 “隱藏” (hide) 繼承自基類的成員函數

這是因為非虛函數是 “靜態綁定” 的,pB 被聲明的是 Shape* 類型的指針,則通過 pB 調用的非虛函數都是基類中的,既使 pB 指向的是派生類

與“靜態綁定”相對的是虛函數的“動態綁定”,即無論 pB 被聲明為 Shape* 還是 Rectangle* 類型,其調用的虛函數取決于 pB 實際指向的對象類型

2 重寫 (override)

在 1.2.2 中提到 override 關鍵字,可以避免派生類中忘記重寫虛函數的錯誤

下面以重寫虛函數時,容易犯的四個錯誤為例,詳細闡述之

class Base {
public:
    virtual void mf1() const;
    virtual void mf2(int x);
    virtual void mf3() &;
    void mf4() const;    // is not declared virtual in Base
};
class Derived: public Base {
public:
    virtual void mf1();        // declared const in Base, but not in Derived.
    virtual void mf2(unsigned int x);    // takes an int in Base, but an unsigned int in Derived
    virtual void mf3() &&;    // is lvalue-qualified in Base, but rvalue-qualified in Derived.
    void mf4() const;       
};  

在派生類中,重寫 (override) 繼承自基類成員函數的實現 (implementation) 時,要滿足如下條件:

一虛:基類中,成員函數聲明為虛擬的 (virtual)

二容:基類和派生類中,成員函數的返回類型和異常規格 (exception specification) 必須兼容

四同:基類和派生類中,成員函數名、形參類型、常量屬性 (constness) 和 引用限定符 (reference qualifier) 必須完全相同

如此多的限制條件,導致了虛函數重寫如上述代碼,極容易因為一個不小心而出錯

C++11 中的 override 關鍵字,可以顯式的在派生類中聲明,哪些成員函數需要被重寫,如果沒被重寫,則編譯器會報錯。

class Derived: public Base {
public:
    virtual void mf1() override;
    virtual void mf2(unsigned int x) override;
    virtual void mf3() && override;
    virtual void mf4() const override;
};  

因此,即使不小心漏寫了虛函數重寫的某個苛刻條件,也可以通過編譯器的報錯,快速改正錯誤

class Derived: public Base {
public:
    virtual void mf1() const override;  // adding "virtual" is OK, but not necessary
    virtual void mf2(int x) override;
    void mf3() & override;
    void mf4() const override;
};   

小結:

1) 公有繼承

  純虛函數 => 繼承的是:接口 (interface)

  普通虛函數 => 繼承的是:接口 + 缺省實現 (default implementation)

  非虛成員函數 =>繼承的是:接口 + 強制實現 (mandatory implementation)

2) 不要重新定義一個繼承自基類的非虛函數 (never redefine an inherited non-virtual function)

3) 在聲明需要重寫的函數后,加關鍵字 override

感謝你能夠認真閱讀完這篇文章,希望小編分享的“C++11中的override有什么用”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永川市| 察雅县| 安西县| 永城市| 辉县市| 定襄县| 永福县| 游戏| 凤台县| 车致| 金坛市| 田阳县| 兴宁市| 黄大仙区| 扬州市| 咸宁市| 彭阳县| 二连浩特市| 新竹市| 湘西| 综艺| 苗栗县| 西畴县| 南岸区| 徐闻县| 舟山市| 东乡县| 平潭县| 桃园市| 临颍县| 博野县| 越西县| 兴宁市| 莎车县| 高邮市| 西乡县| 洞头县| 南岸区| 和硕县| 乾安县| 濮阳县|