effective C++講解了很多我們對繼承認識的誤區,書的最後特別對爲什麼C++要這樣做做了詳細的解釋,瞭解了爲什麼要這樣之後,我們會對繼承機制有更深的瞭解,推薦大家去讀一下。
pdf下載地址:點擊下載:http://download.csdn.net/detail/hanbingfengying/7478915
條款36:區分接口繼承和實現繼承
繼承的概念看起來很簡單,進一步分析,會發現它由兩個可分的部分組成:函數接口的繼承和函數實現的繼承。
這一條重點要我們理解純虛函數、簡單虛函數和非虛函數的區別,它們對應我們想要派生類繼承的僅僅是接口還是接口還是一個缺省實現?
定義純虛函數的目的在於,使派生類僅僅繼承抽象類的接口。
一些函數不能在派生類中重定義,這樣我們就必須把它定義爲非虛函數。
條款37:絕不要重新定義繼承而來的非虛函數
請閱讀下面代碼,查看代碼運行結果:
#include "stdafx.h"
#include <iostream>
using namespace std;
class A{
public:
void func(){
cout << "A" << endl;
}
};
class B: public A{
public:
void func(){
cout << "B" << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
B b;
A *a = &b;
a->func();
b.func();
b.A::func();
return 0;
}
答案是: A B A
相信聰明的你在看了
b.A::func();
這句代碼後立馬就能猜想到其中的原因。
虛函數是動態綁定的,而非虛函數在繼承的時候是靜態綁定的。所以如果子類重定義了非虛函數,就會出現這種僞二義的問題。
條款38:絕不要重新定義繼承而來的缺省參數值
這一條需要格外注意,即使對於有經驗的人來說,這裏也極易出錯。
閱讀下面代碼,查看運行結果:
#include "stdafx.h"
#include <iostream>
using namespace std;
enum ShapeColor { RED, GREEN };
class A{
public:
virtual void func(ShapeColor color = RED){
cout << "red" << color << endl;
}
};
class B: public A{
public:
void func(ShapeColor color = GREEN){
cout << "green" << color << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
cout << "red:0 green:1"<< endl;
B b;
A *a = &b;
a->func();
b.func();
b.A::func();
return 0;
}
運行結果爲
發現派生類對象的func調用了兩次,但是兩次默認的形參值不一樣。
當派生類通過基類對象指針調用繼承的虛函數時,傳的默認形參是基類的默認形參。
這是爲什麼呢?
虛函數是動態綁定而缺省參數值是靜態綁定的。這意味着你最終可能調用的是一個定義在派生類,但使用了基類中的缺省參數值的虛函數:
a->func();
這只是c++繼承的基礎理解,如果你沒有讀過《effective C++》,相信它一定不會讓你失望的。
點擊下載:http://download.csdn.net/detail/hanbingfengying/7478915