实现抽象类的类中的多态函数

时间:2015-02-16 16:07:23

标签: c++ abstract-class

class Eq
{
public:
    virtual bool operator==(Eq operand) = 0;
};

class Day : public Eq
{
public:
    enum DAY
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    } day;
    Day(DAY init_day) : day(init_day){}
    bool operator==(Day operand)
    {
        return day == operand.day;
    }
};

int main()
{
    Day d1(Day::Monday);
    Day d2(Day::Monday);
    d1 == d2;
    return 0;
}

这是我尝试实现的代码。 Eq类就像JAVA的接口一样。它只有一个成员函数,operator ==。运算符==取一个与导出Eq类的类相同类型的操作数。例如,类Day派生Eq,因此它必须实现operator ==,它采用Day类型参数。

还有问题。首先,两个operator ==函数都有不同的签名。所以编译器认为它们不是相同的函数,而是覆盖了函数。其次,如果此代码中的任何函数采用Eq类参数,则编译器会生成错误,因为抽象类的实例不可用。

所以这就是问题所在。如何在T类中使用operator ==函数来获取T类参数,其中T是Eq类的实现?

4 个答案:

答案 0 :(得分:3)

您可以在T中引入类型参数Eq,并从Day派生Eq<Day>以强制执行operator==所需的签名。

答案 1 :(得分:2)

你可以使用CRTP:

template <typename DerivedType>
class Eq
{
public:
    virtual bool operator==(DerivedType operand) = 0;
};

class Day : public Eq<Day>
{
public:
    enum DAY
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    } day;
    Day(DAY init_day) : day(init_day){}
    bool operator==(Day operand)
    {
        return day == operand.day;
    }
};

答案 2 :(得分:2)

您可以通过发送引用来完成此操作。

class Eq
{
public:
    virtual bool operator==(Eq& operand) = 0; // Changed to reference
};

class Day : public Eq
{
public:
    enum DAY
    {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday
    } day;
    Day(DAY init_day) : day(init_day){}
    bool operator==(Eq& operand) // Changed to reference of Eq.
    {
        const Day* other = dynamic_cast<Day*> (&operand);
        if (other == nullptr) // Checking if the operand is of Day type.
            return false; // If not, those two objects cannot be the same.
        return day == other->day; // Do the comparison. 
        // Note the '->' instead of '.' since 'day' is a pointer.
    }
};

与Java相比,你缺少关于C ++如何运作的几个关键点(我猜你更熟悉)。

  1. 要进行虚拟覆盖,您必须使用相同的方法签名。
  2. 为避免切片,您需要发送引用或指针,而不是堆栈中的对象。
  3. 最后,发送值可能会占用大量内存(与引用或指针相比)。
  4. 以下是我发现的一些关于如何在处理继承时执行operator ==重载的好链接。 (他们还谈论公共 - 非虚拟/非公共 - 虚拟讨论。)

    Equality Test for Derived Classes in C++

    What's the right way to overload operator== for a class hierarchy?

答案 3 :(得分:1)

您的方法有两个主要缺陷:

  • operator== Day签名Eq签名不匹配,因此无法正常工作。
  • 您按值传递运算符的操作数。这意味着会有slicing(即传递的对象可能会松散所有不在Eq中的成员,这一天)

已经提出了很好的模板解决方案,这对于这类问题非常方便。为了完整起见,我建议你一个无模板的替代方案。

第一次机会Eq

class Eq
{
public:
    virtual bool operator==(Eq& operand) = 0;  // References passing doesn't slice
};

然后在Day中更新其覆盖:

bool operator==(Eq& operand)
{
    if (dynamic_cast<Day*>(&operand))  // check if types compatible 
        return day == dynamic_cast<Day*>(&operand)->day;
    else return false;  // else the objects are different anyway
}

最后,您可以在main()中进行测试:

 ...
if (d1 == d2)  // check that result is as expected !
    cout << "Yes it works !";  
else cout << "Hhmmm...";