Effective C++看书笔记(6):继承与面向对象设计

继承可以是virtual或non-virtual。

virtual函数意味接口必须被继承。

non-virtual函数意味着接口和实现都必须被继承。

32:确定你的public继承塑模出is-a关系

最重要的规则:pulic继承意味is a。

比如A类继承B类,那么应该代表每一个类型为A的对象同时也使一个类型为B的对象。即B更一般化,A更特殊化。

总结

  • public继承意味is-a。适用于base classes身上的每一件事情一定也适用于继承类身上,因为每一个derived class对象也都是一个base class对象。

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

继承关系的作用域是:派生类作用域被嵌套在基类作用域内。也就是说如果有相同的函数名就会覆盖掉基类。

可以使用using来使基类被覆盖部分可见。

例子

class Base{
    private:
    int x;
    
    public:
    virtual void mf1()=0;
    virtual void mf1(int);
    virtual void mf2();
    void mf3();
    void mf3(double);
}

class Derived:public Base{
   
    public:
    virtual void mf1();
    void mf3();
   	void mf4();
}


//调用
Derived d;
int x;
d.mf1();
d.mf1(x);//错误,因为覆盖了
d.mf2();
d.mf3();
d.mf3(x);//错误,因为覆盖了

//解决办法
class Derived:public Base{
    public:
    using Base::mf1;
    using Base::mf3;
    
    virtual void mf1();
    void mf3();
   	void mf4();
}

d.mf1(x);//现在可以了
d.mf3(x);//

总结

  • derived classes内的名称会遮掩base classes内的名称,在Public继承下从来没有人希望如此。
  • 为了让被遮掩的名称再见天日,可使用using声明式或转交函数。

转交函数即

virtual void mf1()
{
    Base::mf1();
}

34:区分接口继承和实现继承

有时你希望派生类只继承成员函数的接口(也就是声明);有时候你又希望同时继承接口和实现,但又希望能够覆写继承的实现,有时又不允许覆写。

纯虚函数

virtual void draw() const=0;

声明一个pure virtual函数的目的是为了让derived classes只继承函数接口

非纯虚函数的目的是让derived classes继承该函数的接口和缺省实现

virtual void error(const std::string& msg);

如果成员函数是个Non-virtual函数,意味是它并不打算在derived classes中有不同的行为。也就是强制实现。

总结

  • pure virtual函数只具体指定接口继承
  • 普通virtual函数具体指定接口继承及缺省实现继承
  • non-virtual函数具体指定接口继承以及强制性实现继承。

35:考虑virtual函数以外的其他选择

Non-Virtual Interface手法实现template method模式:即通过public非虚函数间接调用private 虚函数。

  • 将机能从成员函数移到class外部函数,带来的一个缺点是,非成员函数无法访问class的non-public成员。
  • tr1::function对象的行为就像一般函数指针。
  • virtual函数的替代方案包括NVI手法及strategy设计模式的多种形式。NVI手法之声是一个特殊形式的template method设计模式。

36:绝不重新定义继承而来的non-virtual函数

即不要覆盖父类的普通函数。

37:绝不重新定义继承而来的缺省参数值

讨论的继承一个带有缺省参数值的virtual函数

virtual函数是动态绑定,缺省参数值是静态绑定。

38:通过复合塑模出has-a或根据某物实现出

复合例子

class Address{};
class PhoneNumber{};
class Person{
    public:
    ....
        private:
    std::string name;
    Address address;
    PhoneNumber number;
    
}
  • 复合的意义和Public继承完全不同
  • 在应用域,复合意味has-a(有一个)
  • 在实现域,符合意味is-implemented-in-terms-of(根据某物实现出)

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

40:明智而审慎地使用多重继承

  • virtual继承会增加大小,速度,初始化(及赋值)复杂度等等成本,如果virtual base classes不带任何数据,将是最具实用价值的情况
  • 多重继承比单一继承复杂,它可能导致新的歧义性,以及对virtual继承的需要。
  • 多重继承的确有正当用途,其中一个情节涉及public继承某个interface class和private继承某个协助实现的class的两相结合。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值