我想实现一个比较派生类的函数。但我发现我必须将基类对象强制转换为派生类对象。
有没有办法避免在这里使用强制转换或其他更好的设计来实现比较功能?
class A {
public :
virtual bool equal(const A & obj) const = 0;
};
class AA : public A{
public:
AA (int i) : m_i(i) {}
virtual bool equal(const A & obj) const
{
return m_i == dynamic_cast<const AA&>(obj).m_i;
}
private:
int m_i;
};
int main () {
AA aa1(10), aa2(9);
A &a1 = aa1, &a2 = aa2;
a1.equal(a2);
return 0;
}
答案 0 :(得分:0)
我在自己的代码中多次被这个请求所困扰。我将提供一个简化的例子:
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)的比较方法,因为相等函数基于指向基类的指针。不幸的是,没有办法告诉从基类派生出多少或所有后代。
为了编程安全,我强烈建议不要在基类中放置虚拟比较运算符。基类应具有声明受保护的比较运算符,仅比较基础数据成员。这种方法将由后代调用。