首页 > 代码库 > 明智而审慎的使用private继承

明智而审慎的使用private继承

private继承的意义在于“be implemented in turns of”。

private继承与public继承时完全不同的,主要体现在两个地方

其一,public继承在子类中保持父类的访问权限,即父类中是public的成员函数或者成员便变量可,在子类中仍是public,对private或protected 的成员函数或成员变量亦是如此;但private继承则不是这样的,他破坏了父类红的访问权限标定,将之转成为private,这对子类本省并无影响,但却影响了子类的子类,子类的子类将无法访问这些声明/定义在爷爷辈类的成员变量或成员函数。

其二,Liskov法则不再使用,也就是“一切父类出现的地方都可以被子类替代”的法则在private这里不成立

#include <iostream>using namespace std;class  Person{};class Student:private Person{};void eat(const Person& p){}int main(){   Person p;   Student s;   eat(p); //ok   eat(s);  //false}

  但如果令Student公有继承Person,则编译器不会报错。这正是Liskov的可替代原则在private继承中不适用的体现。

private继承使用的地方实在不多,除非有一些奇葩的设计需求

class TypeDefine{};class SimpleClass{  int a;  TypeDefine obj;};class SimpleDerivedClass:private TypeDefine{    int a;};int main(){   cout<<sizeof(TypeDefine)<<endl;   cout<<sizeof(SimpleClass)<<endl;   cout<<sizeof(SimpleDerivedClass)<<endl;} 

  第一个类是空类,仅仅是名字的空,看起来是空的,但其实不是这样子的,对于空类,编译器会位子生成默认的函数:默认构造函数,默认拷贝构造函数,,默认析构函数,默认赋值操作符,虽然函数不占空间,但类的每一个对象都须有一个独一无二的内存地址,所以空类的sizeof算出的值是1.非空类因为已经有了成员变量,所以编译器可以利用这些成员变量来进行内存地址的区分,从而表示类的不同对象。

第二个输出的是8,int 4字节再加到空类对象的四字节,理论上编译器还会做一种内存对齐的操作,使得类对象的大小是处理字长的整数倍

第三个输出时4,这其实是编译器做了空白基类优化,原本是要为空白类的对象插入一字节,但因为子类中已经有了对象了,这样理论上就可以凭借这个对象来进行同一个类不同间的识别了,所以这时候编译器就不再插入字节了。

这个结果就是用private继承的好处。

 

明智而审慎的使用private继承