使用继承的赋值运算符



我有以下类:

class Shape
{
protected:
double a, b;
public:
Shape(int a, int b) : a(a), b(b) {}
double area() const { return a*b; }
Shape operator+(const Shape & other)
{
Shape temp(0, 0);
temp.a = a + other.a;
temp.b = b + other.b;
return temp;
}
void operator=(const Shape & other)
{
a = other.a;
b = other.b;
}
};
class Rectangle : public Shape
{
public:
Rectangle(int a, int b) : Shape(a, b) {  }
using Shape::operator=;
};
class Triangle : public Shape
{
public:
double area() { return a*b/2; }
Triangle(int a, int b) : Shape(a, b) {  }
using Shape::operator=;
};

在Rectangle和Triangle类中使用继承的运算符=是否合理?使用它,我可以将形状分配给矩形或三角形,甚至将三角形分配给矩形:

Rectangle r(1, 1);
Triangle t(1, 1);
r = t; // OK

总的来说这样做明智吗?

不,这是不明智的。

首先,Shape::operator=没有做编译器生成的赋值不能做的任何事情:

struct Shape {
double a, b;
Shape(int a, int b) : a(a), b(b) {}
double area() const { return a*b; }
};
struct Rectangle : Shape {
Rectangle(int a, int b) : Shape(a, b) {  }
using Shape::operator=;
};
struct Triangle : Shape {
double area() { return a*b/2; }
Triangle(int a, int b) : Shape(a, b) {  }
using Shape::operator=;
};
int main(){
Rectangle r(1, 1);
Triangle t(1, 1);
r = t;              // OK  !!!
}

在您的示例中,RectangleTriangle(除了它们的area(之间实际上没有区别。当你让Triangle有3个成员时会出现问题(你需要他们来表示一个三角形(:

#include <cassert>
struct Shape {
double a, b;
Shape(int a, int b) : a(a), b(b) {}
double area() const { return a*b; }
};
struct Rectangle : Shape {
Rectangle(int a, int b) : Shape(a, b) {  }
using Shape::operator=;
};
struct Triangle : Shape {
double area() { return a*b/2; }
Triangle(int a, int b,int c) : Shape(a, b) {  }
using Shape::operator=;
double c;
};
int main(){
Rectangle r(1, 2);
Triangle t(1, 1, 2);
Triangle t2(1,2,3);
r = t;                   // OK
t2 = r;
assert( t.c == t2.c);        // should be fine, no?
}

r = t;t2 = r;之后,无辜的读者确实期望t == t2;,但事实并非如此。矩形不是三角形,三角形也不是矩形。如果你真的想让这种转换成为可能,你最好把它定义为explicit

最新更新