重载纯虚拟运算符

时间:2019-06-06 11:23:13

标签: c++ operator-overloading abstract-class derived-class pure-virtual

我有一个抽象类Number,它带有4个纯虚拟运算符(+-/*)。我想制作两个派生类IntegerReal并在那里覆盖这些运算符。我不太了解如何声明运算符。我没有在网上找到与我的情况类似的示例。

我的问题是: 在抽象基类Number中,我的运算符必须返回引用Number&或指针Number*,因为我不能返回抽象类本身。但是我应该以什么作为论点呢? Number&Number*也一样,但是我需要在班级中存储数字,我的基类中是否应该有类似void* num的东西? 想象一下,我有

class Number {
    ...
    virtual Number& operator+(const Number&) = 0;
};

如何在派生类Integer中覆盖此运算符?

1 个答案:

答案 0 :(得分:4)

  

我知道,但是我的导师坚持要像在抽象类中进行练习一样,将其作为覆盖纯虚拟操作符来执行,但是我真的不明白。

好吧,您可以从中了解两件事:

  1. 虚拟函数的一般工作方式(自定义运算符仅是普通函数,仅调用语法有所不同)。
  2. 虚拟功能不是解决任何问题的圣杯。

问题在于类IntegerReal最有可能具有不同的内部表示形式-因此您将无法在不了解具体类型的情况下进行加法/乘法/...。您收到作为第二个操作数。此外,还不清楚混合操作数类型的返回类型应该是什么。

  

我真的不需要atm仅添加real + int real + real,int + int

好吧,我们可以抓住这一点:

class Number
{
public:
    virtual ~Number() { } // in any case, a virtual base class should have a virtual destructor!

    // fine so far:
    virtual Number& operator+(Number const&) const = 0;
    // we are not going to change the          ^
    // own instance, so we'd rather have this operator const
    // (in contrast to operator+=)
};

class Integer : public Number
{
public:
    Integer& operator+(Number const& other) const override
    // ^ co-variant return type, so that's fine
    {
        // at very first, we make sure that we actually received
        // an instance of type Integer
        auto o = dynamic_cast<Integer const*>(&other);
        if(!o)
            // if not, throwing an exception is a good candidate
            // for error handling...
            throw std::invalid_argument("argument must be of type Integer");

        // now as we know it IS an Integer:
        return Integer(this->value + o->value); // or whatever...
        // OOPS - the returned object gets lost when the function is left...
    }
};

如果您也想添加Real,则将进行另一种类型转换。假设Integer + Real产生Real,那么您就不得不将返回类型改回Number

但是,仍然存在一个很大的问题:函数离开后,返回的对象将被销毁,因此返回的引用是悬空的。

我们必须通过某种方式解决此问题。不过,引用并不适合,因此我们可能会选择智能指针:

class Number
{
    virtual std::unique_ptr<Number> operator+(Number const&) const = 0;
};

class Integer : public Number
{
    std::unique_ptr<Number> operator+(Number const& other) const override
    //                 ^
    // unfortunately, now, as ordinary struct, no co-variance possible any more
    {
        return std::make_unique<Integer>(this->value + o->value);
    }
};

这个问题再次说明了实际选择的方法是多么不恰当...