gpt4 book ai didi

c++ - 继承问题

转载 作者:行者123 更新时间:2023-11-30 01:31:07 26 4
gpt4 key购买 nike

这是“Exceptional C++”项目 24 的片段,解决方案,从页面底部开始的第一个项目符号:

Never use public inheritance to implement "IS-ALMOST-A." I've seen some programmers, even experienced ones, inherit publicly from a base and implement "most" of the overridden virtual functions in a way that preserved the semantics of the base class. In other words, in some cases using the Derived object as a Base would not behave quite the way that a reasonable Base client could expect. An example often cited by Robert Martin is the usually misguided idea of inheriting a Square class from a Rectangle class "because a square is a rectangle." That may be true in mathematics, but it's not necessarily true in classes. For example, say that the Rectangle class has a virtual SetWidth(int) function. Then Square's implementation to set the width would also naturally set the height so that the object remains square. Yet there may well exist code elsewhere in the system that works polymorphically with Rectangle objects, and would not expect that changing the width would also change the height. After all, that's not true of Rectangles in general! This is a good example of public inheritance that would violate LSP, because the derived class does not deliver the same semantics as the base class. It violates the key precept of public inheritance: "Require no more and promise no less."

我试过检查它并写道:

// 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;
}

至于我,从 Rectangle 继承 Square 的效果符合预期。那么我哪里弄错了,不明白这个项目符号中说的是什么?
谢谢

最佳答案

重点是 Square 类的语义不同于 Rectangle 类的语义。假设您有一个像这样的通用效用函数:

void doubleArea(Rectangle &rect) {
rect.setWidth(rect.getWidth() * 2);
}

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

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

Square sq(1);
doubleArea(sq);

突然 sq 的面积是通话前的 四倍。您只打算将面积加倍,但得到了错误的结果。

由于 SquareRectangle 不具有完全相同的语义,因此有时对矩形可以执行的操作不适用于正方形。因此,通过从另一个派生一个来声明 Square 是一个 Rectangle 并不是一个好主意,因为派生类不能满足基类。

有关此主题的更多信息,另请参阅 C++ FAQ Lite 条目 "Is a Circle a kind-of an Ellipse?" .

关于c++ - 继承问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3592580/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com