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

Differentiate between inheritance of interface and inheritance of implementation.

public 继承由两部分组成:函数接口(function interfaces)继承和函数实现(function implementations)继承。而不同类型的函数继承程度也是不一样的:

  • 成员函数的接口总是会被继承;

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

  • 声明简朴的(非纯)impure virtual 函数的目的是让 derived classes 继承该函数的接口和缺省实现;

  • 声明 non-virtual 函数的目的是为了让 derived classes 继承函数的接口及一份强制性的实现;

impure virtual 函数的危险

允许 impure virtual 函数同时指定函数声明和函数缺省行为是有潜在危险的,即在 derived class 未明确表明需要继承的情况下就继承了函数的实现。解决的办法有两个,一是切断“virtual 函数接口”和其“缺省实现”:

class Airplane {
public:
    virtual void fly(const Airport& destination) = 0;    // 函数接口
    ...
protected:
    void defaultFly(const Airport& destination);         // 缺省实现
};

class ModelA: public Airplane {
public:
    virtual void fly(const Airport& destination) {       // 明确指明
        defaultFly(destination);
    }
};

class ModelC: public Airplane {
public:
    virtual void fly(const Airport& destination) {       // 明确实现
        ...
    }
};

但是这种做法可能因为过度雷同(defaultFlyfly )的函数名称而引起 class 命名空间的污染。所以有了第二种方法,利用“pure virtual 函数必须在 derived classes 中重新声明,但它们也可以拥有自己的实现“:

class Airplane {
public:
    virtual void fly(const Airport& destination) = 0;
};

void Airplane::fly(const Airport& destination) { ... } // pure virtual 函数的实现,即缺省实现;

class ModelA: public Airplane {
public:
    virtual void fly(const Airport& destination) {
        Airplane::fly(destination);                    // 明确指明;
    }
};

Last updated

Was this helpful?