【Effection C++】读书笔记 条款34~条款35

【Effection C++】继承与面向对象设计

条款34 区分接口继承和实现继承

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

这是有一点需要注意,对于一个函数pure virtual函数的抽象基类是无法实例化的,无论是通过new,还是直接声明对象,编译器都会报错。

但是,对于一个纯虚函数,我们是可以给这个纯虚函数提供相应的函数定义的,并且也可以执行成功,可以通过作用域来指定需要执行的函数。

2. 声明impure virtual函数的目的,是为了让derived class 继承该函数的接口和缺省实现

这种情况下,基类一般提供一种缺省实现,派生类根据自己的实际需求来判断是否需要覆盖基类的缺省实现。

除此之外,如果担心新的派生类因为遗忘了设计独立的实现,而错误的使用了缺省实现,可以参考pure function可以有着相应的定义,但是在调用时候必须明确指明。这种特性帮助我们设计派生类的时候,如果需要缺省实现就明确要求,否则就自己设计。

3. 声明non-virtual的目的是为了让derived class继承函数的接口及一份强制实现

用non-virtual函数的意义在于,其不变性凌驾于特异性之上。

相关代码示例

class Shape
{
public:
    virtual void draw() = 0;                       // 只提供接口
    virtual void error(const std::string& msg);    // 提供接口的同时提供一份默认的实现,派生类可以修改为自己的实现版本
    int objectID() const;                          // 提供接口的同时提供一份强制性的实现,派生类一般不应该修改该实现
};

void Shape::draw()
{
    cout << "Shape::draw()" << endl;
}

void Shape::error(const std::string& msg)   // 接口的默认实现
{
    cout << msg << endl;
}
int Shape::objectID() const                 // 接口的强制实现
{
    return 0;
}

class Rectangle : public Shape
{
    virtual void draw();
};
void Rectangle::draw()
{
    cout << "Rectangle::draw()" << endl;
}

int main()
{
    int id;
    Shape* ps1 = new Rectangle;
    ps1->draw();                            // 调用Rectangle::draw
    ps1->error("Shape::error");             // 调用Shape::error
    id = ps1->objectID();                   // 调用Shape::objectID
    ps1->Shape::draw();                     // 调用Shape::draw()

    return 0;
}

条款35:考虑virtual函数之外的选择

藉由Non-Virtual Interface 手法实现Template Methon模式

这里主要是由设计一个non-virtual函数来设定接口或者执行的框架,但是函数内则调用相应的虚函数来完成具体的实现,这样子,算法的框架整体上相同,但是实现却又不相同。

class GameCharacter{
public:
    int healthValue() const
    {
        ……  //做事前工作
        int retVal=doHealthValue();//真正做实际工作
        ……  //做事后工作
        return retVal;
    }
    ……
private:
    virtual int doHealthValue() const //derived classes可以重新定义
    {
        ……
    }
};

藉由Function Pointer实现Strategy模式

将virtual function 替换为“函数指针成员变量”,这是Strategy设计模式的一种分解表现形式

其他Strategy模式

使用function成员变量替换virtual函数,因而允许任何可调用物搭配一个兼容于需求的签名式。

或者将继承体系中的virtual函数替换为另一个继承体系内的virtual函数。传统的Strategy设计模式的实现手法。

你可能感兴趣的:(读书笔记,effective-c++,c++)