第四章 繼承

C++是一門可面向對象可面向過程編程的語言,當然它和C語言比起的優勢就是面向對象,面向對象是C++的一大特點,那麼,上一講將了面向對象的第一要素,那麼這一講的內容就是面向對象的第二要素——繼承。

為什麼要有繼承?

如果沒有繼承,那麼類僅僅只是具有一些相關行為的數據結構,所以,這僅僅只是對過程語言的一大改進,而繼承的引入,則開闢完全不同的新天地,那麼繼承能夠做些什麼?

使用繼承構建類。

使用繼承擴展功能。

使用繼承實現多態(多態的實現不只是繼承,還有虛函數,兩者缺一不可)。

那麼什麼時候可以使用繼承?簡單點說有一個原則,就是當我們認為“是一個”的時候就可以考慮繼承了,關於“是一個”的概念可能有點模糊,簡單點說就是當我們認為某個東西屬於某類時就可以使用該原則了,比如貓屬於動物,學生也是人,所以這時就可以使用繼承啦。在C++裡面,有“是一個”的概念,同時也有“有一個”的概念,“有一個”和“是一個”這兩個概念可能有時候會有些模糊,當我們理解不清的時候可能會套錯了模型,“是一個”的概念決定我們使用繼承,而且是共有繼承,而“有一個”的概念我們不應該使用共有繼承,更多的時候我們選擇使用複合,當然有時候我們可以使用私有繼承,當然在私有繼承和複合類型之間怎麼決策又有一些技巧性,這裡大家可以通過《C++ Effective》一書進行了解。

使用繼承構建類。

如果按照上面我們的“是一個”的原則去寫代碼可能我們會發現代碼沒法往下寫,因為很多時候“是一個”並不是那麼容易被看透,否則也就沒有多重繼承這種難以理解的語法存在,所以很多時候我們我們使用繼承沒別的想法,僅僅只是想要複用現有的代碼而已。

//+--------------------------

class Super{

public:

Super(){}

virtual ~Super(){}

void doSomeThing(){}

};

class Sub : public Super{

public:

Sub()

void doOtherThing(){}

};

//+---------------------------

我們可以認為Sub就是一個Super,這沒毛病,也合情合理,但是當出現多重繼承的時候,比如:

//+----------------------------

class Super2{

public:

Super2(){}

virtual void ~Super2(){}

void doSomeOtherThing(){}

};

class Sub : public Super,public Super2{

public:

Sub(){}

void doOtherThing(){}

};

//+---------------------------

如果我們現在還在認為Sub是一個Super的話就有點難理解啦,但它確確實實具有Super和Super2的功能,他們確確實實也滿足“是一個”的原則(否則多態也就沒有意義),但是這裡我們似乎要澄清一件事,這裡並非是因為Sub滿足“是一個”才使用繼承(當然或許我們設計之初就是這麼考慮的),而是因為被繼承才被是一個,嗯,好吧,理解起來有些拗口,所以我們才這麼認為繼承可以用來構建類,是一個或許只是它附加的一個功能。

和使用繼承構建類比起,使用繼承擴展功能似乎更好理解一些,因為它是實實在在的是一個,我們要的也就是這個是一個原則,比如我們手裡有一個處理字符串的類——String,而現有的接口都是該String的引用作為參數,而我們想要在新的開發中使用更加便捷的String,但同時有需要使用原有依賴該String的一些接口功能,所以我們不可能重新實現一個String,我們應該做的就是擴展這個String,子類化一個類出來,他提供有我們需要的功能,同時他還是一個String,那些使用String引用作為參數的接口依然不受任何任何影響:

//+--------------------------

class MyString : public String{

public:

……

using String::append;// 加入基類的append只能接受字符串

template

void append(const T& val){

std::ostringstream os;

os<

String::append(os.str());

}

……

};

void testFun(const String& str){

std::cout<

}

int main(){

MyString str;

str.append(123); // 調用子類的append

str.append(","); // 調用基類的append

str.append(128.82);// 調用子類的append

std::cout<

testFun(str);

return 0;

}

//+----------------------------

這就是典型的使用繼承去擴展現有功能的例子啦,那麼我們下面看看繼承的一些高級用法,我們將思路回到前面的點上,我們不再去考慮擴展功能這件事,我們只想如何做好一件事,比如想要編寫一個類,他具有比較大小,判斷是否相等的操作,那麼我們可以如下:

//+---------------------------

class MObj{

public:

MObj(){}

virtual ~MObj(){}

friend bool operator

friend bool operator>(const MObj& obj,const MObj& obj2);

friend bool operator==(const MObj& obj,const MObj& obj2);

friend bool operator!=(const MObj& obj,const MObj& obj2);

……

};

//+---------------------------

如果我們上面所見,當我們想要實現這些功能,我們需要完成四個函數的編寫,如果我們需要再編寫一個類也需要這些操作,那麼我們又得重新再來一遍,這……如果一個兩個還好,要是我們經常這麼幹一定很不爽,所以這就是我們這裡要說的重點,我們只需要完成一部分操作就能夠實現全部操作即可,比如我們規定,當我們提供operator,同時提供operator==以及提供operator!=等其他操作。

//+---------------------------

template

class CmpOrder{

public:

friend bool operator>(const T& left,const T& right){

return !(left < right);

}

friend bool operator == (const T& left, const T& right){

return !(left < right) && !(left > right);

}

friend bool operator!=(const T& left, const T& right){

return !(left == right);

}

};

//+-----------------------------

這是一個通用的比較基類,所以只需要我們的類繼承至該類而且實現operator

//+-----------------------------

class MInt : public CmpOrder{

private:

int mVal;

public:

MInt(int v) :mVal(v){}

friend bool operator

return left.mVal < right.mVal;

}

};

int main(){

MInt val1(7);

MInt val2(8);

std::cout << (val1 < val2) << std::endl;

std::cout << (val1 > val2) << std::endl;

std::cout << (val1 == val2) << std::endl;

std::cout << (val1 != val2) << std::endl;

system("pause");

return 0;

}

//+-------------------------------

當然這種操作手法有一個奇怪的名字,叫奇特的遞歸模板模式,他的模式:

//+-------------------------------

class Sub : public Super{……};

//+-------------------------------

他使用模板加繼承的手法實現一些強大的功能,當然還有一些更奇怪的繼承方法我們後續在實踐中慢慢說,比如:

//+-------------------------------

template

class Sub : public Sub{……}

template<>

class Sub{}

//+--------------------------------

這種繼承手法能夠實現一些功能強大的組件,比如我們可以以此為基礎實現一個數據庫。

好吧,繼承我們就暫時介紹到這裡,接下來還有多態等著說呢。

每天會更新論文和視頻,還有如果想學習c++知識在晚上8.30免費觀看這個直播:https://ke.qq.com/course/131973#tuin=b52b9a80


分享到:


相關文章: