学完Efficient c++ (32-33)

27 篇文章 0 订阅
24 篇文章 0 订阅

条款32:确定你的public继承保证了is-a关系

public继承的意思是:子类是一种特殊的父类,这就是所谓的“is-a”关系(适用于基类身上的每一件事情一定也适用于继承类身上)。但是本条款指出了其更深层次的意义:在使用public继承时,子类必须涵盖父类的所有特点,必须无条件继承父类的所有特性和接口(因为我们可以认为每一个派生类对象也都是一个基类对象。之所以单独指出这一点,是因为如果单纯偏信生活经验,会犯错误。

比如鸵鸟是不是鸟这个问题,如果我们考虑飞行这一特性(或接口),那么鸵鸟类在继承中就绝对不能用public继承鸟类,因为鸵鸟不会飞,我们要在编译阶段消除调用飞行接口的可能性;但如果我们关心的接口是下蛋的话,按照我们的法则,鸵鸟类就可以public继承鸟类。同样的道理,面对矩形和正方形,生活经验告诉我们正方形是特殊的矩形,但这并不意味着在代码中二者可以存在public的继承关系,矩形具有长和宽两个变量,但正方形无法拥有这两个变量——没有语法层面可以保证二者永远相等,那就不要用public继承。

所以在确定是否需要public继承的时候,我们首先要搞清楚子类是否必须拥有父类每一个特性,如果不是,则无论生活经验是什么,都不能视作”is-a”的关系。public继承关系不会使父类的特性或接口在子类中退化,只会使其扩充。

条款 33:避免遮掩继承而来的名称

之前我们了解过 C++ 名称查找法则,这在继承体系中也是类似的,当我们在派生类中使用到一个名字时,编译器会优先查找派生类覆盖的作用域,如果没找到,再去查找基类的作用域,最后再查找全局作用域。名称遮盖问题——名称在作用域级别的遮盖是和参数类型以及是否虚函数无关的,即使子类重载了父类的一个同名,父类的所有同名函数在子类中都被遮盖。

考虑以下情形:

class Base {
public:
    void mf();
    void mf(double);
};

class Derived : public Base {
public:
    void mf();
};

这样会导致派生类无法使用来自基类的重载函数,因为派生类中的名称mf掩盖了来自基类的名称mf

对于名称掩盖问题的一种方法是使用using关键字:

class Derived : public Base {
public:
    using Base::mf;
};

using关键字会将基类中所有使用到名称mf的函数全部包含在派生类中,包括其重载版本。

若有时我们不想要一个函数的全部版本,只想要单一版本(特别是在private继承时),可以考虑使用转发函数(forwarding function)

class Base {
public:
    virtual void mf();
    virtual void mf(double);
};

class Derived : public Base {
public:
    virtual void mf() {
        Base::mf();
    }
};

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值