【Effective C++】6. 继承与面向对象设计

发布时间:2024年01月24日

Item32 确定你的public继承关系建模出is-a的关系

public继承的含义:

  • is-a:student是一种person,person的范围更大
  • 在函数传参的过程,eta能同时接受person和student两种变量,反之不能
class Person {};
class Student : public Person {};

void eta(const Person& p) {}
void study(const Student& s) {}

int main() {
    Person p;
    Student s;
    eta(p);
    eta(s);
    study(s);
    study(p);
    return 0;
}

/*
 * 报错信息
main.cpp:11:11: error: invalid initialization of reference of type ‘const Student&’ from expression of type ‘Person’
   11 |     study(p);
      |           ^
In file included from main.cpp:3:
item_32.h:14:27: note: in passing argument 1 of ‘void study(const Student&)’
   14 | void study(const Student& s) {}
*/

通过public继承建模,应该慎重思考父类和子类的关系,考虑下面两个例子

  • 企鹅是一种鸟,但是不会飞,建模方式1不太恰当
  • 如果方式2不需要区分会飞和不会飞,建模2显得多余
  • 方式3将编译器能够限制的错误推迟到了运行期,同样不恰当
  • 方式4不定义这样的方法,如果子类觉得有必要在定义,有更广的应用范围
// 建模方式1
class Bird {
public:
    virtual void fly() {}
};
class Penguin : public Bird {};

// 建模方式2
class Bird {};
class FlyingBird : public Bird {
public:
    virtual void fly() {}
};
class Penguin : public Bird {};

// 建模方式3
class Bird {
public:
    virtual void fly() {}
};
class Penguin : public Bird {
public:
    virtual void fly() {  error(); }
};

// 建模方式4
class Bird {};
class Penguin : public Bird {};
  • ?如果是正方形继承自长方形,可以看出结果不符合预期
class Rectangle {
public:
    virtual void setHeight(int newHeight);
    virtual void setWidth(int newWidth);
    virtual int height() const;
    virtual int width() const;
};
class Square : public Rectangle {};
void makeBigger(Rectangle& r) {
    int oldHeight = r.height();
    r.setHeight(r.width() + 10);
    assert(r.height() == oldHeight);
}

Square s;
makeBigger(s); // 结果不符合预期

文章来源:https://blog.csdn.net/GouDanAndOcean/article/details/135832306
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。