你所不知的private继承
你所不知的private继承
在C++的类中有许多种继承方式,而我们在软件设计和编写代码时用得最多的就是public继承,我们很少接触到private继承。但是我们在设计时真的有思考过什么时候应该用public继承,什么时候不该使用public继承,什么时候应该想想那些经常被我们遗忘的知识,让我们从它们被遗忘的角落里重拾它的光芒。例如private继承。
As we all know,public继承是塑模出一种is-a关系。什么是is-a的关系呢?Effective C++这样描述:如果你令class D以public形继承class B,那么每一个类型为D的对象同时也是一个类型为B的对象,反之不成立。意思是B比D表现出更一般化的概念,而D比B表现出更特殊化的概念。你主张“B对象可派上用场的地方,D对象一样可以派上用场”,因为每一个D对象都是一种(是一个)B对象。反之如果你需要一个D对象,B对象无法效劳。
还有就是我们喜欢用的virtual函数,即运行动态也是建立在public继承之上的。
在我刚学C++时,只知道private继承,使继承而来的成员(public成员和protected成员)都成为private,至于它有没有什么更深一层的意义和作用就没有去思考了,只是理想当然地把它认为是不想这些成员被它的以后的子类继承。那private继承到底意味着什么呢?
先看看下面的代码:class Person{...};class Student:private Person{...};void eat(const Person &p);Person p;Student s;eat(p);//正确eat(s);//错误
再看看Effective C++的说法:如果classes之间的继承关系是private,编译器不会自动将一个deirved class对象转换为一个base class对象。private继承意味着implemented-in-terms-of(根据某物实现出)。如果你让class D以private继承class B,你的用意是为了采用class B内已经备妥的某些特性,不是因为B对象和D对象存在有任何观念上的关系。private继承纯粹是一种实现技术,意味着只有实现部分被继承,接口部分应该略去。如果D以private形式继承B,意思是D对象根据B对象实现而得,private继承在软件设计层面上没有意义,其意义只及于软件实现层面。
private有点has-a的感觉。它的意义与复合的意义相同。那我们的问题又产生了,什么时候用复合什么时候用private继承?答案很简单,尽可能使用复合。除了以下的2种情况:1、private继承通常比复合的级别低。但是当derived class需要访问protected base class的成员,或需要重新定义继承而来的virtual函数时,就要用private继承。2、private继承可以造成empty class最优化。
- 2楼eastcowboy昨天 21:05
- 还有就是我们喜欢用的virtual函数,即运行动态也是建立在public继承之上的。n==================n这个观点不正确。n但凡继承,都可以有virtual函数,都可以运行的时候动态确定调用哪个函数。nn“如果classes之间的继承关系是private,编译器不会自动将一个deirved class对象转换为一个base class对象。”n==================n这是Effective C++中的原话吗?手边没书,没法确认。n但其实不是这样的。但凡继承,都可以进行派生类指针到基类指针的转换,只不过要注意可访问性。n如果是public继承,那可以在任意位置执行这种转换。n如果是private继承,那就需要在class内部,或者friend,才可以执行这种转换。n如果是protected继承,在class内部,或者friend,或者派生类中,才可以执行这种转换。n当然,把private继承解释为“根据XX来实现”是合理的。nn[code=cpp]class Bn{npublic:n virtual ~B() { printf("destruct B\n"); }n virtual void print() { printf("B::print\n"); }n};nnclass D : private Bn{npublic:n virtual ~D() { printf("destruct D\n"); }n virtual void print() { printf("D::print\n"); }nn friend B* CreateB();n};nnB* CreateB()n{n return new D; // yes,派生类指针转为基类指针n}nnint main()n{n B* b = CreateB();n b->print(); // yes,虚函数调用n delete b;nn return 0;n}[/code]nn输出:nD::printndestruct Dndestruct B
- Re: ljianhui11小时前
- 回复eastcowboyn{还有就是我们喜欢用的virtual函数,即运行动态也是建立在public继承之上的。}这句是我自己写的,而{“如果classes之间的继承关系是private,编译器不会自动将一个deirved class对象转换为一个base class对象。}是Effective C++的内容。你说的我也试过,是行的。学习了。但是还是有的不同的,就是当继承是多层时,下面是我的代码:n#include <iostream>nusing namespace std;nclass Bn{ntpublic:nttvirtual void print(){cout<<"class B"<<endl;}tn};nclass Dpub:public Bn{tttn};nclass Dpri:private Bn{tntpublic:nttfriend B* creatDpri(){return new Dpri;}tttn};nn//class DD:private Dprin//{ttn//tpublic:n//ttfriend B* creatDD(){return new DD;}tttn//};nnclass DDpub:public Dpubn{n};nnint main()n{ntB *pb = new B;ntB *pdpub = new Dpub;ntB *pdpri = creatDpri();n//tB *pdd = creatDD();ntB *pddpub = new DDpub;ntntpb->print();ntpdpub->print();ntpdpri->print();n//tpdd->print();ntpddpub->print();ntdelete pb;ntdelete pdpub;ntdelete pdpri;n//tdelete pdd;ntdelete pddpub;ntsystem("pause");ntreturn 0;tn}n注释了的是不能通过编译的,错误信息为: `class B' is inaccessible within this context In function `B* creatDD() `B' is an inaccessible base of `DD'
- 1楼oCanZi昨天 14:45
- 看完顺便赚积分··············