Представьте, что у меня есть абстрактный базовый класс 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 ++, чтобы понять, почему.