![](https://csdnimg.cn/release/download_crawler_static/2422772/bg7.jpg)
C++的风格与技巧
7
当 protected 部分发生了改变时,使用 Shape 的代码必须重新编译——即使只有派生类
的实现部分才能够访问 protected 成员。
于是,基类中的“实现相关的信息”(information helpful to implementers)对
用户来说变成了象接口一样敏感的东西,它的存在导致了实现部分的不稳定,用户代码的无
谓的重编译(当实现部分发生改变时),以及将头文件无节制地包含进用户代码中(因为“实
现相关的信息”需要它们)。有时这被称为“脆弱的基类问题”(brittle base class
problem)。
一个很明显的解决方案就是,忽略基类中那些象接口一样被使用的“实现相关的信息”。换
句话说,使用接口,纯粹的接口。也就是说,用抽象基类的方式来表示接口:
class Shape {
public: //使用 Shapes 的用户的接口
virtual void draw() const = 0;
virtual void rotate(int degrees) = 0;
virtual Point center() const = 0;
// ...
// 没有数据
};
class Circle : public Shape {
public:
void draw() const;
void rotate(int) { }
Point center() const { return center; }
// ...
protected:
Point cent;
Color col;
int radius;
// ...
};
class Triangle : public Shape {
public:
void draw() const;
void rotate(int);
Point center() const;
// ...
protected:
Color col;
Point a, b, c;
// ...
};
现在,用户代码与派生类的实现部分的变化之间的关系被隔离了。我曾经见过这种技术使得
编译的时间减少了几个数量级。
但是,如果确实存在着对所有派生类(或仅仅对某些派生类)都有用的公共信息时怎么办呢?
可以简单把这些信息封装成类,然后从它派生出实现部分的类:
class Shape {
public: //使用 Shapes 的用户的接口
virtual void draw() const = 0;