4

考虑以下抽象类:

class Abstract {
public:
    // ...

    virtual bool operator==(const Abstract& rhs) const = 0;

    // ...
};

现在假设我正在从这个抽象类创建多个派生类。但是,在与自己的类型进行比较时,每个都使用不同的算法,在与任何其他派生类进行比较时使用通用算法。在以下两个选项之间,哪个是更好、更有效的选项?

选项 A:

class Derived : public Abstract {
public:
    // ...

    bool operator==(const Abstract& rhs) const {
        // Code for comparing to any of the other derived classes
    }

    bool operator==(const Derived& rhs) const {
        // Code for comparing to myself
    }

    // ...
};

选项 B:

class Derived : public Abstract {
public:
    // ...

    bool operator==(const Abstract& rhs) const {
        const Derived* tmp = dynamic_cast<const Derived*>(&rhs);
        if (tmp) {
            // Code for comparing to myself
        }
        else {
            // Code for comparing to any of the other derived class
        }
    }
};

我真的很好奇这些选项有什么优点和缺点,因为 C++ 类型转换对我来说是一个相对神秘的话题。此外,哪种解决方案更“标准”,第二种解决方案对性能有影响吗?

可能有第三种解决方案吗?特别是如果有很多派生类,每个派生类都需要针对不同派生类的特殊比较算法?

4

4 回答 4

2

您的两种方法适用于不同的情况。对于选项 A,使用静态类型rhs来决定调用哪个函数,对于选项 B,使用动态类型。

因此,如果您希望您的程序根据参数的“真实”类型选择其行为,我认为您应该选择第二个选项。如果可以在编译时知道类型,则应使用选项 A,因为它提供了更好的性能。

于 2011-09-17T02:43:49.097 回答
1

您实际上可以使用其中一种技术来实现双重调度的第三种方式。这种方法在“更有效的 C++”的第 31 条中有完整的描述。这是一个小例子:

#include <iostream>

class Derived1;
class Derived2;

class Base
{
public:
    virtual bool operator==( Base& other) = 0;
    virtual bool compare( Base& other) {return false;}
    virtual bool compare( Derived1& other) {return false;}
    virtual bool compare( Derived2& other) {return false;}
};

class Derived1 : public Base
{
public:
    virtual bool operator==( Base& other) {return other.compare(*this);}

    virtual bool compare( Base& other) {return false;}
    virtual bool compare( Derived1& other) {return true;}
};

class Derived2 : public Base
{
public:
    virtual bool operator==( Base& other) {return other.compare(*this);}

    virtual bool compare( Base& other) {return false;}
    virtual bool compare( Derived2& other) {return true;}
};

int main()
{
    Base *a = new Derived1;
    Base *b = new Derived1;
    Base *c = new Derived2;

    std::cout << (*a == *b) << std::endl;
    std::cout << (*a == *c) << std::endl;
    return 0;
}

输出:

1
0
于 2011-09-17T08:35:16.483 回答
1

如果您期望 == 运算符使用参数的动态类型,我认为选项 B 就是您正在寻找的。例如:

class base
{
public:
  virtual bool operator ==( const base& other ) = 0;
};

class derived : public base
{
public:
  bool operator ==( const base& other ) { return false; }
  bool operator ==( const derived& other ) { return true; }
};


int main()
{
  base* a = new derived;
  base* b = new derived;
  std::cout << ( *a == *b ) << std::endl;
}

这打印:

0

所以 operator ==( const base & other ) 被调用,即使实际的动态类型是派生的。

于 2011-09-17T02:50:47.773 回答
0

不幸的是,C++ 没有多种方法可以根据动态类型信息选择要调用的当前函数。您需要双重调度、访问者模式或其他一些技巧来实现该行为。

于 2011-09-18T00:39:54.563 回答