C++之明智审慎地使用private继承(39)---《Effective C++》

来源:互联网 发布:cloudzoom.js 编辑:程序博客网 时间:2024/05/23 11:35

条款39:明智而审慎地使用private继承

C++中public继承被视为一种“is-a”关系,private继承并不是“is-a”关系,只是is-implemented-in-terms-of关系,private继承意味着只有实现部分被继承,接口部分被略去。
下面我们来看看private继承的一些特性:

class Person{...};class Student:private Person{...};void eat(const Person& p);void study(const Student& s);Person p;Student s;eat(p);eat(s);//error,因为private继承不满足“is-a”关系,编译器不会自动将子类对象还原为父类对象

1)因为private继承并不满足“is-a”关系,仅仅满足is-implemented-in-terms-of关系,private继承只是部分继承,编译器不会自动将一个derived class对象转换为一个base class对象。
2)由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原本是protected或者public属性。

class Timer{public:    explicit Timer(int tickFrequency);    virtual void onTick() const;    ...};class Widget:private Timer{private:    virtual void onTick() const;    ...};

策略:

由于复合和private继承都满足is-implemented-in-terms-of关系,当我们面对一个“并不存在is-a关系”的两个classes,其中一个需要访问另一个的protected成员,或需要重新定义其一或者多个virtual函数,那么继承一定是必要的,单纯的复合已经无法解决了,可以采用“复合+继承”策略,同时private继承极有可能成为正统设计策略。

如果考虑过“复合+继承”策略之后,不适合我们才选用private继承。

最后让我们看一个private继承的例子,加深对上面部分的理解:

#include <iostream>#include <string>using namespace std;class Base{public:    Base(int xx) :x(xx){    }    void show(){        cout << x << endl;    }    virtual void guessWhat()const = 0;    virtual ~Base(){    }private:    int x;};class Derived :private Base{public:    Derived(int x) :Base(x){    }    virtual void guessWhat()const{        cout << "I'm so grateful for meeting you!!!" << endl;    }    void show(){        cout << "Derived::show" << endl;        Base::show();    }};int main(){    Derived d(10);    d.show();    d.guessWhat();    return 0;}

运行结果:
这里写图片描述
总结:

1)private继承意味着is-implemented-in-terms-of关系,他通常比复合的级别低,但是当derived class需要访问protected base class中的成员,或者需要重新定义继承而来的virtual函数时,这么设计是合理的;
2)和复合不同,private继承可能造成empty base最优化,这对致力于“对象尺寸最小化”的程序库开发者来说,可能非常重要。

阅读全文
0 0
原创粉丝点击