Я был укушен этим запросом много раз в своем собственном коде. Я представлю упрощенный пример:
struct Fruit
{
virtual bool is_equal(Fruit const & f) const = 0; // Compare two fruits
// Some dangerous actions:
bool operator==Fruit const & f)
{
return is_equal(f); // Dispatch!
}
};
struct Strawberry : public Fruit
{
bool is_equal(Fruit const & f)
{
bool equal = false;
// The f could be any fruit, such as tomatoes or pineapples or bananas.
// Need to perform a dynamic_cast to verify that the f is a strawberry.
Strawberry const & s = dynamic_cast<Strawberry const &>(f);
// perform strawberry comparison;
return equal;
};
}
struct Banana : public Fruit
{
bool is_equal(Fruit const & f)
{
bool equal = false;
// The f could be any fruit, such as tomatoes or pineapples or strawberries.
// Need to perform a dynamic_cast to verify that the f is a banana.
Banana const & b = dynamic_cast<Banana const &>(f);
// perform banana comparison;
return equal;
};
}
bool Compare_Fruits(Fruit const * pf1, Fruit const * pf2)
{
if (*pf1 == *pf2)
{
cout << "Fruits are equal\n";
return true;
}
cout << "Fruits are different\n";
return false;
}
int main(void)
{
// Fun with fruit.
Fruit * p_fruit_1 = new Strawberry;
Fruit * p_fruit_2 = new Banana;
Fruit * p_fruit_3 = new Strawberry;
// Is this valid, comparing two different fruits, when
// we just want to compare two strawberries?
if (Compare_Fruits(p_fruit_1, p_fruit_3)) // OK, both are strawberries
{
// ...
}
if (Compare_Fruits(p_fruit_1, p_fruit_2)) // Not OK, two different fruits.
{
// ...
}
return 0;
}
Дело в том, что если вы реализуете равную работу в базовом классе, так что потомки могут сравнить экземпляры, вы сделали плохое решение. Имейте в виду, что я могу передать указатель на экземпляр одного потомка (Strawberry) методу сравнения другого потомка (Banana), потому что функция равенства основана на указателях на базовый класс. К сожалению, нет способа рассказать, сколько или всех потомков, полученных из базового класса.
Для обеспечения безопасности программирования я настоятельно рекомендую не размещать виртуальные операторы сравнения в базовом классе. Базовый класс должен иметь операторы сравнения, объявленные защищенными, что сравнить только базовые элементы данных. Этот метод будет вызываться потомками.
Помните, что 'dynamic_cast' для ссылочного типа может вызывать исключение. Может быть, лучше использовать вместо указателя вместо этого, вы, вероятно, просто хотите вернуть 'false', если указатель возвращается NULL. –
Может быть, используя getter, который является виртуальным в базовом классе для переменной-члена 'm_i'? – abiessu
Подробнее о двойном отправке и о классическом решении для него - образец посетителя. – Ilya