1. 程式人生 > >[C++]關於C++中繼承、過載、掩蓋

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

關於C++中繼承、過載、掩蓋

MoaKap

在開始之前,我們可以先看下面這個小程式:

#include <iostream>

using namespace std;

class Base

{

private:

int x;

public:

virtual void mf1()

{

cout<<"Base: mf1()"<<endl;

}

virtual void mf1(int)

{

cout<<"Base: mf1(int)"<<endl;

}

virtual void mf2()

{

cout<<"Base: mf2()"

<<endl;

}

void mf3(double)

{

cout<<"Base: mf3(double)"<<endl;

}

};

class Derived: public Base

{

public:

virtual void mf1()

{

cout<<"Derived: mf1()"<<endl;

}

void mf3()

{

cout<<"Derived: mf3()"<<endl;

}

void mf4()

{

cout<<"Derived: mf4()"<<endl;

}

};

int main()

{

Derived d;

int x = 100;

d.mf1();

d.mf1(x);

d.mf2();

d.mf3();

d.mf3(x);

d.mf4();

}

如果你能很清楚地搞清楚各個函式的呼叫過程,那以下的內容你就不要再浪費時間了。否則,就耐心學習以下~~

首先,我們必須弄清楚的就是C++的名字掩蓋規則。在C++中,區域性的變數能夠掩蓋相同名稱的全域性變數,而這種掩蓋對於函式一樣起作用。注意這裡是名字的掩蓋,而不管函式的引數、返回值等其它因素。所以只要名字相同,就會被掩蓋。

接著,就是分清子類與基類作用域的關係。C++中子類作用域被巢狀在基類作用域內。這樣,當編譯器檢查到一個函式名時,首先從最裡層作用域開始查詢,一層一層向外查詢函式,如果找到函式宣告,就停止查詢。因此,裡層的函式會覆蓋外層作用域的函式。

class Base

{

private:

int x;

public:

virtual void f1()=0;

virtual void f2();

void f3();

...

};

class Derived: public Base

{

public:

virtual void f1();

void f4();

...

}

如上面這段程式碼,類的作用域關係如圖。

現在我們來分析文章開頭的程式。

d.mf1(); //沒問題,輸出 Derived: mf1() ,因為子類的mf1()函式覆蓋了基類的mf1()

d.mf1(x);//錯誤!子類的mf1()覆蓋了基類的mf1(int)。名字相同即覆蓋,與引數無關

d.mf2();//沒問題,子類繼承了基類的mf2()函式,輸出Base: mf2()

d.mf3();//沒問題,直接呼叫子類函式,輸出 Derived: mf3()

d.mf3(x);//錯誤!子類的mf3()覆蓋了基類的mf3()mf3(double)

d.mf4();//沒問題

那麼,如果想要在子類中既繼承基類的函式,同時子類的函式不覆蓋基類成員函式,可以使用using宣告式。

在子類中加入下面的using宣告式:

using Base::mf1;

using Base::mf3; //讓基類內名為mf1mf3的所有東西在子類作用域中都可見,不被覆蓋

然後,我們再使用d.mf1(x); d.mf3(x);就沒問題了。這時,就繼承了基類的成員函式,同時過載函式,並且名字不被覆蓋。

使用using宣告式將基類的所有同名函式在子類中都可見,但有時候,在私有繼承的子類中,我們並不想繼承所有這些函式,比如我們只想繼承無引數的mf1()函式,這時可以使用轉交函式來實現。

class Derived: private Base

{

public:

virtual void mf1()//轉交函式

{

Base::mf1();//暗自成為inline

}

...

}

轉交函式的另一用途就是為那些不支援using宣告式的老式編譯器使用,將繼承而來的名稱匯入子類作用域中。

Effective C++

Derived classes內的名稱會掩蓋base classes內的名稱。在public繼承下一般不希望如此。

為了讓被遮掩的名稱再見天日,可使用using宣告式或轉交函式。