首页 > 解决方案 > 虚函数覆盖是否违反 LSP?

问题描述

我正在学习设计模式,但我认为 C++ 虚函数重写违反了 LSP。

  1. 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。

  2. 子类可以添加自己独特的方法。

  3. 当子类重写或实现父类的方法时,方法的前置条件(即方法的形参)比父类的输入参数更宽松。

  4. 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)比父类更严格。

但是为了实现多态性,我必须重写(覆盖)。难道是我理解错了?

class Animal;
class Cat;

void fun(Animal *xyz) { xyz->eat(); }

class Animal
{
 public:
    virtual void eat() { ::std::cout << "I'm eating generic food."; }
};

class Cat : public Animal
{
  public:
    // override.
    // Whether it violates the principle?
    void eat() { ::std::cout << "I'm eating a rat."; }
};

标签: c++design-patternsliskov-substitution-principle

解决方案


LSP 要求子类必须遵守其超类的合同。

这意味着您提到的关于参数和返回类型的 4 条规则,但是合同还可以包含许多代码中未捕获的内容(尽管如果在注释中捕获它会很好!)。

没有其他要求,所以除非Animal's 合同中有规定必须只吃普通食品,否则您的替代是可以的。如果有这样的规则,那么您不应该将eat方法设为虚拟。


推荐阅读