想象一下,我有抽象基类 Shape
、派生类Circle
和Rectangle
.
class Shape {};
class Circle : public Shape {};
class Rectangle : public Shape {};
Shape*
假设我有两个指针,我需要确定两个形状是否相等。(这是因为我有两个实例,vector<Shape*>
我想看看它们是否具有相同的形状。)
推荐的方法是双重调度。我想出的是这个(这里大大简化了,所以形状等于所有其他相同类型的形状):
class Shape {
public:
virtual bool equals(Shape* other_shape) = 0;
protected:
virtual bool is_equal(Circle& circle) { return false; };
virtual bool is_equal(Rectangle& rect) { return false; };
friend class Circle; // so Rectangle::equals can access Circle::is_equal
friend class Rectangle; // and vice versa
};
class Circle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
protected:
virtual bool is_equal(Circle& circle) { return true; };
};
class Rectangle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
protected:
virtual bool is_equal(Rectangle& circle) { return true; };
};
这可行,但我必须为每个派生类添加一个单独的equals
函数和friend
声明。Shape
然后我也必须将完全相同的equals
函数复制粘贴到每个派生类中。这是一个非常多的样板,比如 10 种不同的形状!
有没有更简单的方法来做到这一点?
dynamic_cast
是不可能的;太慢了。(是的,我对其进行了基准测试。速度在我的应用程序中很重要。)
我试过这个但它不起作用:
class Shape {
public:
virtual bool equals(Shape* other_shape) = 0;
private:
virtual bool is_equal(Shape& circle) { return false; };
};
class Circle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
private:
virtual bool is_equal(Circle& circle) { return true; };
};
class Rectangle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
private:
virtual bool is_equal(Rectangle& circle) { return true; };
};
equals()
即使在相同的形状上,也总是返回 false。is_equal(Shape&)
即使有“更具体的”匹配可用,调度似乎总是选择基本功能。这可能是有道理的,但我对 C++ 调度的理解不够深入,无法知道原因。