《Effective C++读书笔记》--条款34:区分接口继承和实现继承

来源:互联网 发布:淘宝禁售手机卡 编辑:程序博客网 时间:2024/05/29 12:48

当我们设计一个类的时候,我们会希望其子类只继承成员函数的接口,但有时候又希望其继承接口和实现,但又希望能重写他们所继承的接口和实现或者不允许重写任何东西。我们首先要明确public继承含义,即is-A的关系,对于基类成立的所有条件,对其public继承的子类一定成立,反之则不然。

当我们希望子类继承该函数的接口时,我们可将该函数在基类中定义为纯虚函数,此时基类是不可被实例化的,其中代表的含义是“你必须提供一个该函数的实现,但设计者不干涉你如何去实现他”,比如设计一个人类,吃东西的函数是必须的,但设计者不关心你是用筷子吃还是刀叉吃,只需要实现即可。

当我们希望子类继承该函数的接口和实现时,我们就可写一个虚函数(虚函数的继承要求是函数名,返回值,参数类型均相同,这与子类中和父类的同名函数导致隐藏的规则不同,其中的同名函数值得是函数名相同,而其他参数可以不同)。其代表的含义是“你需要写一个该函数,如果你自己不想写,可以使用基类的该函数”,比如一个人类,吃东西的函数是必须的,但同时为你提供了一个默认用筷子吃东西的函数,你可以自己实现用刀叉吃东西的函数,也可以使用默认的用筷子吃东西的函数。

对于以上两种情况的结合来说,如果我们需要继承接口和默认实现,但又不想使我们忘记重写该函数导致调用了默认版本,我们可以将接口与实现分离开,例如以下代码

public:    virturl void eat() = 0;protected:    void defaulteat()    {         cout << "use chopstick";    }

如果我们想使用默认版本,就继承该接口同时在函数体内调用defaulteat(),否则我们就自己加以实现。与该设计类似的实现方法还有一种,也是本人在Qt中遇到过的实现方法:

也就是在子类的实现中调用父类的版本。

最后,对于非虚函数来说,他表示对继承的子类的一份强制实现,并且任何子类都不应该尝试去修改。
对于以上关于继承的讨论我们需要知道虚函数,纯虚函数和不同成员函数在继承中的意义,我们在设计类的时候,一要考虑继承的成本,二要考虑多态的灵活性,

public:    virtual void eat()    {         cout << "chopstick eat";    }  
class Derive:public Base{     void eat()    {        Base::eat();    }}
 
阅读全文
0 0
原创粉丝点击