基類派生新類的過程包括三個步驟:吸收基類成員、改造基類成員和添加新的成員。C 類繼承中,派生類包含了它所有基類的除構造、析構函數之外的所有成員。對基類成員的改造包括兩個方面,第一個是基類成員的訪問控制問題,依靠派生類定義時的繼承方式來控制。第二個是對基類數據或函數成員的覆蓋,對基類的功能進行改造。派生類新成員的加入是繼承與派生機制的核心,是保證派生類在功能上有所發展的關鍵。可以根據實際情況的需要給派生類添加适當的數據和函數成員,來實現必要的新增功能。同時,在派生過程中,基類的構造函數和析構函數是不能被繼承下來的,一些特别的初始化和掃尾清理工作,需要加入新的構造和析構函數。
對于類成員的三類訪問屬性,及三種繼承方式形成的派生類繼承父類變更後的訪問屬性,這些訪問屬性的訪問控制需要站在不同的使用主體去理解,這些使用主體可以分為4類:
在于protected訪問屬性和protected繼承,除了需要分4類訪問主體以外,還要區分三個繼承層次。
protected訪問屬性對于派生類來說相當于是public,是透明的,對于外部函數來說相當于private,是封閉的。
最難理解的就是私有繼承了,為什麼會有這種方式,繼承過來後,public和protected部分都成了私有屬性,外界不能訪問?這有什麼意義?不要忘了,雖然派生類的對象不能訪問基類中的任何的成員,但該繼承層次的成員函數是可以訪問的。其意義在于私有繼承可以幫助我們複用基類代碼,并防止基類接口的曝光。
#include <iostream>
using std::cout;
using std::endl;
class engine {
public :
void start() {cout << "engine->start" << endl;}
void move() {cout << "engine->move" << endl;}
void stop() {cout << "engine->stop" << endl;}
void others() {cout << "engine->others" << endl;}
};
class wheel {
public :
void start() {cout << "wheel->start" << endl;}
void move() {cout << "wheel->move" << endl;}
void stop() {cout << "wheel->stop" << endl;}
void test() {cout << "wheel->test" << endl;}
};
class car : private engine, private wheel {
public :
void start();
void move();
void stop();
void test();
};
void car::start() {
engine::start();
wheel::start();
others(); // 私有繼承的公有成員成了私有成員
}
void car::move() {
engine::move();
wheel::move();
}
void car::stop() {
engine::stop();
wheel::stop();
}
void car::test(){
wheel::test(); // 如果直接寫test(),則是遞歸調用,會stackover
}
int main(int argc, char* argv[]) {
car ca;
ca.start();
ca.move();
ca.stop();
ca.test();
getchar();
return 0;
}
/*
engine->start
wheel->start
engine->others
engine->move
wheel->move
engine->stop
wheel->stop
wheel->test
*/
類car私有繼承自類engine和類wheel,類car的三個成員函數start()、move()、stop()分别通過調用類engine和類wheel的成員函數實現,這樣做的好處在于不需要重寫而直接使用繼承自基類的函數,同時因為是私有繼承,能通過類car的對象調用,而不能直接調用類engine和類wheel的函數,防止不必要函數的曝光,因為對于使用類car對象的用戶來說并不需要關心start()、move()、stop()的具體實現過程,也不需要控制engine和wheel的動作。
private繼承就是一種純粹的實現技術,意味着子類繼承了父類,純粹是看中了父類裡面的某些函數實現罷了,不想跟你有别的關系,這個新的類将不會與父類指針有關系(接口都變private了)。
一般來說私有繼承,與複合類的作用類似,可以互換(複合類更容易理解)。
在私有繼承情況下,為了保證基類的一部分外部接口特征能夠在派生類中也存在,就必須在派生類中重新聲明同名的成員。利用派生類成員函數對私有成員(基類public、protected成員private繼承後轉變為私有成員)的訪問能力,把基類的原有成員函數的功能照搬過來。這種在派生類中重新聲明的成員函數具有比基類同名成員函數更小的作用域,因此在調用時,根據同名覆蓋的原則,自然會使用派生類的函數。在面向對象的程序設計中,若要對基類繼承過來的某些函數功能進行擴充和改造,可以通過這樣的覆蓋來實現。這種覆蓋的方法,是對原有成員改造的關鍵手段,是程序設計中經常使用的方法。
比如有這麼一個時間類 , 另一個widget也想有超時的功能:
class Timer{
public:
virtual void timeout(){ cout << __FUNCTION__ << endl;} //用于計算超時功能
};
class Widget: private Timer{ //private 繼承
private: //這裡也改private 或許比較好,如果是public接口,有可能不太好哦.客戶誤意味widget居然有超時!
virtual void timeout() {
Timer::timeout(); //調用父類的超時功能
cout << __FUNCTION__ << endl; //幹自己的事
}
};
類似這種情況下就可以使用 private 繼承 。如果改成public 繼承或許有些奇怪,比如: Timer *pt = new Widget; ??? 好像兩者沒啥關系呢(private繼承時,Timer *pt = new Widget;會出錯,public繼承OK)。
private繼承意味着派生類隻想獲取并适當加工基類的某些函數實現。
-End-
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!