effective C++ 第六章

OOP:面向对象编程。
该章讲的是继承与面向对象设计
条款32:确定你的public 继承塑模出 is-a关系
    一个重要规则是公开继承意味着一种关系。
    is-a并非是唯一存在于classes之间的关系。另两个常见的关系是has-a和is-implemented-in-terms-of
    public继承意味着is-a。适用于base classe s身上的每一件事也一定适用于derived classes身上,因为每一个derived class对象也都是一个base class对象。
条款33:避免遮掩继承而来的名称
    derived classes内的名称会遮掩base classes内的名称。在public继承下从来没有人希望如此。
    为了让被遮掩的函数重见天日,可使用using 声明式或转交函数
class Base{
public:
    virtual void mf1()=0;
    virtual void mf1(int);
    .........
};
class Derived:private Base{
public:
    virtual void mf1()//转交函数
{
    Base::mf1();}//暗自成为inline
......
};
Derived d;
int x;
d.mf1();//很好,调用的是Derived::mf1
d.mf1(x);//错误!Base::mf1()被遮掩了
条款34:区分接口继承和实现继承
public继承经过更严密的检查之后,发现它由两部分组成:函数接口继承和函数实现继承。
class  Shape{
public:
    virtual void draw() const= 0;
    virtual void error (const std::string& msg);
    int objectID() const;
    .....
};
class Rectangle:public Shape{...};
class Ellipse:public Shape{....};

纯虚函数有两个最突出的特性:他们必须被任何继承了他们的具象class重新声明,而且他们在抽象class中通常没有定义。你就会明白:
声明一个纯虚函数是为了让子类只继承函数接口。
这对Shape::draw函数是再合理不过的事了,因为所有Shape对象都应该是可绘出的,这是合理的要求。但Shape class 无法为此函数提供合理的缺省实现,毕竟椭圆绘法迥异于矩形绘法Shape::draw的声明式乃是对具象子类设计者说:“你必须提供一个draw函数,但我不干涉你怎么实现它”
Shape* ps=new Shape;//错误!Shape是抽象的
Shape* ps1=new Rectangle;//没问题
ps1->draw();//调用Rectangle::draw()
Shape* ps2=new Ellipse;//没问题
ps2->draw();//调用Ellipse::draw
ps1->Shape::draw();//调用Shape::draw()
ps2->Shape::draw();//调用Shape::draw()
非纯虚函数和虚函数不同,一如往常,子类继承其函数接口,但非纯虚函数会提供一份实现代码,derived classes可能会覆写它。
声明纯虚函数的目的,是让子类继承该函数接口和缺省实现。
class Shape{
public:
    virtual  void error (const std::string&msg);
    ....
};



其接口表示,每个class都必须支持一个“当遇上错误时可调用”的函数,但每个class可自由处理错误。如果某个class不想针对错误做出任何特殊行为,它可以退回到Shape class 提供的缺省错误处理行为
但是,允许非纯虚函数同时指定函数声明和函数缺省行为,却有可能造成危险!
假设XYZ航空公司设计的飞机继承体系,有A型和B型飞机两者都以相同方式飞行。因此XYZ设计这样的继承体系
非虚函数具体指定接口继承以及强制性实现继承

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务