首页 > 代码库 > private 继承 真的没用吗??

private 继承 真的没用吗??

private继承,在看到effective C++之前,我发现在我之前的代码里面,没有用到这个机制,但是认真回想起还是有一些影子。

大多数人认为private继承是没有用的,其实不然,在某些情况下,它也会带给你一些惊喜。


好,言归正传,之前已经数次提到过 public继承表示的是  “is   a ”的关系,也就是说每一个derived对象D同时也是base对象,任何在base对象上的操作可以实施到derived对象身上。


例如

class Person{....};
class Student::public Person{...};

Person p;
Student s;

void eat(Person *p);
void study(Student &s);

eat(s);//可以施加到Person身上的操作,对于Student对象仍然使用。
eat(p); 


但是,如果将上述的public继承改为private继承,eat(s) 调用将会失败。


那么,private继承到底意味着什么,首先很直观的讲,上述的Student对象并没有转化为Person对象,其次,由

private继承而来的所有Base的成员在Derived中均是private属性的(无论其原先在Base类中的属性是public或者是

protected)。


最重要的一点,private继承意味着 “ is   implemented as ...” (以某物来实现),也就意味着,Derived类只是继承

了Base类中的属性,并未继承其接口。这是实现层面上的事儿。


值得注意的是,复合 的意义也是  “ is   implemented as ...” (以某物来实现),这似乎还是印证了那句 “private继承无用”。


关于此二者的权衡,很简单,在两者均可以的情况下,选择使用 复合,而不是private继承, 除非在一些很特殊的情况,接下来的几

个例子就是用来讲二者的区别。


假设:

我们需要定义一个类 Timer 来统计当前类 Widget 所处的状态,例如函数调用次数等,那么我们需要一个这样的类来实现这样的功能。

定义可以如下:


class Timer{
public: explicit Timer(int ticks);
virtual ontick() const;//需要计数的类继承此函数,
...
};


显然,在Widget类中需要使用Timer类的对象,采用 public 继承显然是不合适的,因为两者没有从属关系。那么想到了private继承。

并且重定义了ontick函数。


class Widget:public Timer
{
private:
virtual ontick() const;
...
};


注:此处将ontick函数定义在private部分,是为了不让类的对象误认为可以调用ontick函数(该函数为private, 无论定义在什么位置)。


显然,这是可行的,那么使用复合难道就不可以了 吗?显然是可以的,并且鼓励使用复合,只需要在Widget的内部定义一个值属于该类自身的一个类用来继承Timer类,即:


class Widget
{
    private:
        class TimerManager:public Timer
        {
            public:
                void ontick() const;
                ...
        };
        TimerManager timer;
        ...

};

这个设计比上述的private继承更易理解。还有一点很有意思,在此处假设 Widget 是意欲成为Base class的类,也就

是说其他的类会继承Widget 如果你使用private继承的话,那么Widget 的derived 类可能会修改了ontick 函数(毕竟这

也是它的基类的虚函数)。

但是,如果需要在该函数中重写Timer中的virtual函数,那么选择private继承就是必须的了。


次,如果是 private 继承,在定义Widget 类的时候,Timer类必须是可见的,也就是说必须有包含 “Timer.h” 字样,

可是在复合中,完全可以使用 Pointer to  Implement  (pImpl)技术,在Widget类定义一个TImer的指针即可,这里就

只需要Timer的声明,从而降低了编译的耦合性


但是对于如下的极端例子:要继承的类是空类


class Empty{};
class HasAInt
{
    private:
        int a;
        Empty e;
};

上述的   sizeof( hasAInt ) > sizeof( int ) ; 对于空类占用空间的说明见 http://blog.csdn.net/xuqingict/article/details/24433311


但是使用private继承。C++编译器便有一种称作  “ 空白基类最优化的” 原则,是的sizeof(hasAInt) == sizeof(int);

(注:此原则只对单一继承有效),这对于 那些对对象尺寸要求很严格的程序来说,可能很重要。



综上所述:private继承不是没有用的,但是如果可以采用复合实现相同的功能,那就对它敬而远之吧。