c语言继承与派生(C简单理解private继承及其应用场合)
基类派生新类的过程包括三个步骤:吸收基类成员、改造基类成员和添加新的成员。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-
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com