继承问题

The*_* do 1 c++ inheritance

这是来自"Exceptional C++"的第24项,解决方案,页面底部的第一个子弹:

永远不要使用公共继承来实现"IS-ALMOST-A".我已经看到一些程序员,甚至是经验丰富的程序员,从基础公开继承并以保留基类语义的方式实现"大多数"被覆盖的虚函数.换句话说,在某些情况下,使用Derived对象作为Base将不会像合理的Base客户端所期望的那样运行.罗伯特·马丁经常引用的一个例子是从Rectangle类继承Square类通常被误导的想法"因为正方形是一个矩形".这在数学中可能是正确的,但在课堂上并不一定如此.例如,假设Rectangle类具有虚拟SetWidth(int)函数.然后广场' 设置宽度的实现也会自然地设置高度,使对象保持方形.然而,在系统的其他地方可能存在与Rectangle对象一起使用多态的代码,并且不会期望更改宽度也会改变高度.毕竟,对于一般的矩形来说,情况并非如此!这是违反LSP的公共继承的一个很好的例子,因为派生类不提供与基类相同的语义.它违反了公共继承的关键原则:"不再需要,也不能承诺." 这是违反LSP的公共继承的一个很好的例子,因为派生类不提供与基类相同的语义.它违反了公共继承的关键原则:"不再需要,也不能承诺." 这是违反LSP的公共继承的一个很好的例子,因为派生类不提供与基类相同的语义.它违反了公共继承的关键原则:"不再需要,也不能承诺."

我试过检查它,我写道:

// Square.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;
class Rectangle
{
private:
 unsigned width_;
 unsigned height_;
public:
 Rectangle(const unsigned width, const unsigned height):width_(width),height_(height)
 {/*Empty body*/ }
 unsigned GetWidth()const
 {
  return width_;
 }
 unsigned GetHeight()const
 {
  return height_;
 }
 virtual void SetWidth(const unsigned width)
 {
  width_ = width;
 }
 void SetHeight(const unsigned height)
 {
  height_ = height;
 }
 virtual ~Rectangle()
 {
  cout << "~Rectangle()" << '\n';
 };
};

class Square : public Rectangle
{
 using Rectangle::SetWidth;
public:
 Square(const unsigned width):Rectangle(width,width)
 {
 }
 void SetWidth(const unsigned width)
 {

  SetWidth(width);
  SetHeight(width);
 }
 ~Square()
 {
  cout << "~Sqare()" << '\n';
 }
};

int _tmain(int argc, _TCHAR* argv[])
{
 Rectangle** a = static_cast<Rectangle**>(operator new (sizeof(Rectangle) * 2));
 a[0] = new Rectangle(10,10);
 a[1] = new Square(5);
 Rectangle* r = a[0];
 cout << r->GetHeight() << "\t" << r->GetWidth() << '\n';
 r = a[1];
 cout << r->GetHeight() << "\t" << r->GetWidth() << '\n';
 r = a[0];
 r->SetWidth(20);//here I'm setting just width for a Rectangle
 cout << r->GetHeight() << "\t" << r->GetWidth() << '\n';
delete a[1];
delete a;
     return 0;
    }
Run Code Online (Sandbox Code Playgroud)

至于我从Rectangle继承Square是按预期工作的.那我在哪里弄错了,不明白这个子弹中的内容是什么?
谢谢

sth*_*sth 5

关键是Square该类的语义与该类的语义不同Rectangle.假设你有一个像这样的通用实用函数:

void doubleArea(Rectangle &rect) {
  rect.setWidth(rect.getWidth() * 2);
}
Run Code Online (Sandbox Code Playgroud)

目的是调用该函数将使给定Rectangle的面积(宽度×高度)加倍.

使用派生Square类,您现在可以执行以下操作:

Square sq(1);
doubleArea(sq);
Run Code Online (Sandbox Code Playgroud)

在电话会议之前,突然sq四倍的面积.你只打算将面积加倍,但得到了错误的结果.

由于Square没有完全相同的语义Rectangle,有时对矩形可以做的事情不适用于正方形.因此它不是宣称一个好主意SquareRectangle通过派生从另一个,因为派生类不能满足所有的基类作出的要求/承诺.

有关此主题的更多信息,请参阅C++ FAQ Lite条目"圆是一种椭圆吗?" .

  • 很好的例子.语义契约是关键. (3认同)