动态强制转换或函数重载?

时间:2011-09-17 02:32:56

标签: c++ inheritance casting overloading dynamic-cast

考虑以下抽象类:

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 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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 &amp; other)。

答案 2 :(得分: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

答案 3 :(得分:0)

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