1. 程式人生 > >c++ 覆蓋、過載、隱藏

c++ 覆蓋、過載、隱藏

“overload”翻譯過來就是:超載,過載,過載,超出標準負荷;“override”翻譯過來是:重置,覆蓋,使原來的失去效果。

先來說說過載的含義,在日常生活中我們經常要清洗一些東西,比如洗車、洗衣服。儘管我們說話的時候並沒有明確地說用洗車的方式來洗車,或者用洗衣服的方式來洗一件衣服,但是誰也不會用洗衣服的方式來洗一輛車,否則等洗完時車早就散架了。我們並不要那麼明確地指出來就心知肚明,這就有過載的意思了。在同一可訪問區內被聲名的幾個具有不同引數列的(引數的型別、個數、順序不同)同名函式,程式會根據不同的引數列來確定具體呼叫哪個函式,這種機制叫過載,過載不關心函式的返回值型別。這裡,“過載”的“重”的意思不同於“輕重”的“重”,它是“重複”、“重疊”的意思。例如在同一可訪問區內有:

① double calculate(double);

② double calculate(double,double);

③ double calculate(double, int);

④ double calculate(int, double);

⑤ double calculate(int);

⑥ float calculate(float);

⑦ float calculate(double);

六個同名函式calculate,①②③④⑤⑥中任兩個均構成過載,⑥和⑦也能構成過載,而①和⑦卻不能構成過載,因為①和⑦的引數相同。

覆蓋是指派生類中存在重新定義的函式,其函式名、引數列、返回值型別必須同父類中的相對應被覆蓋的函式嚴格一致,覆蓋函式和被覆蓋函式只有函式體(花括號中的部分)不同,當派生類物件呼叫子類中該同名函式時會自動呼叫子類中的覆蓋版本,而不是父類中的被覆蓋函式版本,這種機制就叫做覆蓋。

下面我們從成員函式的角度來講述過載和覆蓋的區別。

成員函式被過載的特徵有:

1) 相同的範圍(在同一個類中);

2) 函式名字相同;

3) 引數不同;

4) virtual關鍵字可有可無。

覆蓋的特徵有:

1) 不同的範圍(分別位於派生類與基類);

2) 函式名字相同;

3) 引數相同;

4) 基類函式必須有virtual關鍵字。

比如,在下面的程式中:

#include <iostream.h>

class Base

{

public:

void f(int x){ cout << "Base::f(int) " << x << endl; }

void f(float x){ cout << "Base::f(float) " << x << endl; }

virtual void g(void){ cout << "Base::g(void)" << endl;}

};

class Derived : public Base

{

public:

virtual void g(void){ cout << "Derived::g(void)" << endl;}

};

void main(void)

{

Derived d;

Base *pb = &d;

pb->f(42); // 執行結果: Base::f(int) 42

pb->f(3.14f); // 執行結果: Base::f(float) 3.14

pb->g(); // 執行結果: Derived::g(void)

}

函式Base::f(int)與Base::f(float)相互過載,而Base::g(void)被Derived::g(void)覆蓋。

隱藏是指派生類的函式遮蔽了與其同名的基類函式,規則如下:

1) 如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏(注意別與過載混淆)。

2) 如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆)。

比如,在下面的程式中:

#include <iostream.h>

class Base

{

public:

virtual void f(float x){ cout << "Base::f(float) " << x << endl; }

void g(float x){ cout << "Base::g(float) " << x << endl; }

void h(float x){ cout << "Base::h(float) " << x << endl; }

};

class Derived : public Base

{

public:

virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }

void g(int x){ cout << "Derived::g(int) " << x << endl; }

void h(float x){ cout << "Derived::h(float) " << x << endl; }

};

通過分析可得:

1) 函式Derived::f(float)覆蓋了Base::f(float)。

2) 函式Derived::g(int)隱藏了Base::g(float),注意,不是過載。

3) 函式Derived::h(float)隱藏了Base::h(float),而不是覆蓋。

看完前面的示例,可能大家還沒明白隱藏與覆蓋到底有什麼區別,因為我們前面都是講的表面現象,怎樣的實現方式,屬於什麼情況。下面我們就要分析覆蓋與隱藏在應用中到底有什麼不同之處。在下面的程式中bp和dp指向同一地址,按理說執行結果應該是相同的,可事實並非如此。

void main(void)

{

Derived d;

Base *pb = &d;

Derived *pd = &d;

// Good : behavior depends solely on type of the object

pb->f(3.14f); //執行結果: Derived::f(float) 3.14

pd->f(3.14f); //執行結果: Derived::f(float) 3.14

// Bad : behavior depends on type of the pointer

pb->g(3.14f); //執行結果: Base::g(float) 3.14

pd->g(3.14f); //執行結果: Derived::g(int) 3

// Bad : behavior depends on type of the pointer

pb->h(3.14f); //執行結果: Base::h(float) 3.14

pd->h(3.14f); //執行結果: Derived::h(float) 3.14

}

請大家注意,f()函式屬於覆蓋,而g()與h()屬於隱藏。從上面的執行結果,我們可以注意到在覆蓋中,用基類指標和派生類指標呼叫函式f()時,系統都是執行的派生類函式f(),而非基類的f(),這樣實際上就是完成的“介面”功能。而在隱藏方式中,用基類指標和派生類指標呼叫函式f()時,系統會進行區分,基類指標呼叫時,系統執行基類的f(),而派生類指標呼叫時,系統“隱藏”了基類的f(),執行派生類的f(),這也就是“隱藏”的由來。


===================================================================
-------------------------------------------------------------------
-------------------------------------------------------------------

過載(overload)
這個好理解,在同個space域同名的.
引數必須不同,有關virtual無關.


覆蓋(override)
同名字,同參數,有virtual

覆蓋好理解比如show()函式
A派生了B
如果B中的show()覆蓋了A中的show()
但B中仍然有兩個show(),而不管是A類指標也好,B類物件呼叫也好,都只能呼叫B類自己的那個show();
而從A類繼承過來的show()函式真的就被覆蓋了,沒有了嗎? 答應是不對的.這時可以在B類物件顯示的呼叫A類繼承過來的show();

程式程式碼:
#include <iostream>
using namespace std;
class A
{
      public:
             virtual void show()
             {
                  cout << a << endl;
             }
             
             int a;
};
class B:public A
{
      public:
             void show()
             {
                  A::show();  
//顯示的呼叫自己類中的 "由A類繼承過來的show()函式"
//像這種直接顯示指出某個類的某個函式時,
//編譯器處理方式是這樣的: 首先在自己類中找有沒有A::show(),如果找到,呼叫.不在繼續在A類中找
//如果找不到,則在顯示指出的那個類中(即A類)呼叫那個函式. 這裡當然是在B類中可以找到A::show()
//因為基類中指出了這個函式是virtual函式.
             }
             int b;
};

int main()
{
    A a;
    a.a = 3;
    a.show();
    B b;
    b.b = 4;
    b.show();
    b.A::show(); //顯示的呼叫自己類中的 "由A類繼承過來的show()函式"
    return 0;
}

總結:
virtual, 覆蓋.
其實準確,通俗的講B類還是有兩個show(),只是呼叫由A繼承過來的show()只能通過顯示的呼叫方法 [類名::virtual函式名]
而不管是基類A的指標 (B b; A *p = &b; p->show())或者派生類的物件(B b; b.show()),都只能呼叫B類的自己本身存在的show()函式

-----------------------------------------------------------------------------------------------------------------------

隱藏hide
這個有點麻煩了...
什麼是隱藏情況?
1,同名同參無virtual
2,同名不同參不管有無virtual

程式程式碼:
class A
{
     public:
           void show() {};  //編號1
           void rose(int a) {}   //編號2
};
class B:public A
{
     public:
           void show() {}; //編號3
           void rose(int a, int b) {};  //編號4
};
//
類B中的show()和rose()明顯是隱藏了類A的show()和rose()
隱藏的理解:
B類中其實有兩個show(),兩個rose();
但為什麼不叫過載呢?你會這樣想,但我可以告訴你,因為類B中的兩個show(),兩個rose(),不是都可以被類B物件呼叫的.

//----1----//
編號1和編號2,在類B中哪怕存在,但只能通過類A的指標呼叫,而不能通過B類物件呼叫,如:


程式程式碼:
A *p = new B;
p->show(); 
p->rose(3);
p->rose(3,5); //error

//----2----//
編號3和程式設計4,只能通過類B物件呼叫,而不能通過類A的指標呼叫,如:


程式程式碼:
B b;
b.show();
b.rose(3,5);
b.rose(4); //error
 

相關推薦

C++ 覆蓋過載隱藏

“overload”翻譯過來就是:超載,過載,過載,超出標準負荷;“override”翻譯過來是:重置,覆蓋,使原來的失去效果。 先來說說過載的含義,在日常生活中我們經常要清洗一些東西,比如洗車、洗衣服。儘管我們說話的時候並沒有明確地說用洗車的方式來洗車,或者用洗衣服的

c++中的隱藏過載覆蓋(重寫)

類過載是c++動態多型,普通函式的過載是靜態多型 成員函式被過載的特徵: (1)相同的範圍(在同一個類中); (2)函式名字相同; (3)引數不同; (4)virtual關鍵字可有可無。  覆蓋是指派生類函式覆蓋基類函式,特徵是: (1)不同的範圍(分別位於派生

c++中的過載覆蓋隱藏

引用:http://blog.csdn.net/Kendiv/archive/<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2006/04/25/675940.aspx<?xm

C++中的覆蓋過載隱藏

    c++中類本身之間的函式關係與基類和子類之間的函式關係有:覆蓋、過載與隱藏。 1>覆蓋:C++中在基類用virtual定義的函式在子類中重新定義,此時稱為覆蓋,即子類對父類函式的覆蓋。 2>過載:同一個類中定義了多個同名但其形參不同的函式,這些同名函式之

c++ 覆蓋過載隱藏

“overload”翻譯過來就是:超載,過載,過載,超出標準負荷;“override”翻譯過來是:重置,覆蓋,使原來的失去效果。 先來說說過載的含義,在日常生活中我們經常要清洗一些東西,比如洗車、洗衣服。儘管我們說話的時候並沒有明確地說用洗車的方式來洗車,或者用洗衣服的方式來

C++中函式過載隱藏覆蓋和重寫的區別 轉自:http://www.bijishequ.com/detail/277975?p=

程式碼編譯執行環境:VS2012+Debug+Win32 1.函式過載(Function Overload) 1.1定義 C++規定在同一作用域中,同名函式的形式引數(指引數的個數、型別或者順序)不同時,構成函式過載。 1.2用法 比如,要從兩個變數中返回其中較

C++】物件函式的覆蓋過載多型

覆蓋 Coverage 在基類中定義了一個非虛擬函式,然後在派生類中又定義了一個同名同參數同返回型別的函式,既是覆蓋 在派生類物件上直接呼叫這個函式名,則只會呼叫派生類中的同名函式 #include <iostream> using namespace std;

C++快速入門繼承機制中的構造器和析構器訪問限制覆蓋過載友元

繼承機制中的構造器和析構器 構造器是類初始化建立時呼叫的方法 --構造器的名字就是類的名字 析構器是類執行完後記憶體回收執行的方法 --析構器的名字~類名字 舉例看下在程式碼中執行的順序吧 /* 繼承機制中的構造器和析構器 */ #include

c++中overload過載override覆蓋overwrite重寫的介紹與區別

(1)overload(過載),即函式過載: ①在同一個類中; ②函式名字相同; ③函式引數不同(型別不同、數量不同,兩者滿足其一即可); ④不以返回值型別不同作為函式過載的條件。 (2)override(覆蓋,子類改寫父類的虛擬函式),用於實現C++中多型: ①分別位於父類和子類中; ②子類改寫父

C++函式的過載重寫與隱藏

1、幾個概念與區別 (1)函式重寫:也稱作覆蓋,是用於類的繼承中,函式名、引數個數、型別都相同,僅函式體不同。 (2)函式過載:是指同一作用域的不同函式使用相同的函式名,但是引數個數或型別不同。 (3)函式隱藏:既不是過載也不是重寫

繼承 過載覆蓋的概念及其用法

一:繼承 1.繼承的概念: 是對現有的類加以利用,併為其新增新功能的一種有效途徑。通過繼承來重複使用原有的程式碼(再生), 一般需要保持“基礎類”不變,只是將這兒或哪兒的東西串聯起來,以達到預期的效果,然而,繼承並不是在現有類基礎上製造新類的唯一方法。 通過“合

C++精進篇(八)之―函式重定義過載重寫重入

 C++函式重定義、過載、重寫、重入 1. 重寫 (override):        父類與子類之間的多型性。子類重新定義父類中有相同名稱和引數的虛擬函式。        函式重寫的特點: (1)不同的範圍,分別位於基類和派生類中 (2)重寫函式必須有相同的型別,名稱和

初識C++之函式過載重寫重定義的區別

在C++的學習中,慢慢接觸了一些很容易混淆的名詞,今天就來剖析幾個容易混淆的名詞。 1、函式過載   過載函式是函式的一種特殊情況,為方便使用,C++允許在同一範圍中宣告幾個功能類似的同名函式,但是這些同名函式的形式引數(指引數的個數、型別或者順序)必須不同

[C++]函式的過載重寫和重定義的區別

#include <iostream> using namespace std; class Base { public: // ========================================================================= // 子類和

重寫覆蓋過載多型幾個概念的區別分析

override->重寫(=覆蓋)、overload->過載、polymorphism -> 多型 override是重寫(覆蓋)了一個方法,以實現不同的功能。一般是用於子類在繼承父類時,重寫(重新實現)父類中的方法。 重寫(覆蓋)的規則:    1、重寫方

[C++]關於C++中繼承過載掩蓋

關於C++中繼承、過載、掩蓋 MoaKap 在開始之前,我們可以先看下面這個小程式: #include <iostream> using namespace std; class Base

關於VB.NET基類繼承過載隱藏的總結歸納

文章主要介紹了VB.NET基類的繼承,重寫,過載,隱藏,VB.NET類成員訪問的修飾符Friend,private ,protected,protected friend,public 。 很喜歡用VB.NET開發語言,在網上也經常收集,自己也總結了一點小筆記,在這裡共大家參考一下,本文主要對V

Java基礎複習第八天:繼承過載this與super多型static

一 繼承 1.繼承的由來 多個類中有相同成員變數和成員方法,那麼我們會把這些共性抽取到另外一個類中, 這時多個類只需要繼承剛剛抽取出來這個類即可 2.父類 和 子類 一個類A 繼承了 類B,那麼 類B稱為父類/超類/基類(superclass) 類

重寫過載重定義

(1)重寫(override):重寫也可以看做覆蓋,子類重新定義父類中具有相同名稱和引數的虛擬函式,函式特徵相同,但函式的具體實現不同,它主要在繼承關係中出現。被重寫的函式不能是static的,但必須是virtual的。 (2)過載(overload):過載是函式名相同,引

函式 預設值過載內聯

#include<iostream> using namespace std; inline void fun(int i,int j=20,int k=30); inline void