C ++ Despacho doble para iguales ()
Imagina que tengoabstract clase base Shape
, con clases derivadasCircle
yRectangle
.
class Shape {};
class Circle : public Shape {};
class Rectangle : public Shape {};
ecesito determinar si dos formas son iguales, suponiendo que tengo dosShape*
punteros. (Esto se debe a que tengo dos instancias devector<Shape*>
y quiero ver si tienen las mismas formas.)
La forma recomendada de hacer esto es doble despacho. Lo que se me ocurrió es esto (muy simplificado aquí, para que las formas sean iguales a todas las demás formas del mismo tipo):
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; };
};
Esto funciona, pero tengo que agregar un @ separaequals
función yfriend
declaración enShape
para cada clase derivada. Luego tengo que copiar y pegar laexactamente el mismoequals
función en cada clase derivada, también. ¡Este es un montón de repeticiones, por ejemplo, 10 formas diferentes!
dynamic_cast
está fuera de la cuestión; demasiado lento. (Sí, lo comparé. La velocidad es importante en mi aplicación).
Intenté esto pero no funciona:
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()
siempre devuelve falso, incluso en formas idénticas. Parece que el despacho siempre elige lais_equal(Shape&)
función base, incluso cuando hay una coincidencia "más específica" disponible. Esto probablemente tiene sentido, pero no entiendo el envío de C ++ lo suficientemente bien como para saber por qué.