如何覆盖子类中的operator +

时间:2016-11-18 14:59:11

标签: c++ operator-overloading

我有CharRow类有这样的字段:

protected:
 char* ptr;
 int ROW_MAX_LENGTH;

并且有子类BigIntegerNumber(char数组)。 我的算子+在CharRow中:

   virtual CharRow operator+ (CharRow row2)
{
    int row1Length = this->getRowCurrentLength();
    int row2Length = row2.getRowCurrentLength();

    CharRow tempRow(row1Length + row2Length);

    for(int i = 0; i < row1Length; i++){
        tempRow.ptr[i] = this->ptr[i];
    }

    for(int i = 0; i < row2Length; i++){
        tempRow.ptr[i + row1Length] = row2.ptr[i];
    }

    return tempRow;
}

我需要以多态方式调用operator+

BigIntegerNumber operator+ (BigIntegerNumber row2)
{
    BigIntegerNumber temp(this->getRowCurrentLength() + row2.getRowCurrentLength());
    temp = BigIntegerNumber::addValue(*this, row2);
    return temp;
}

2 个答案:

答案 0 :(得分:0)

虚拟operator + can work in general,但要使其发挥作用,必须满足一些限制条件。

在你的情况下它不起作用的第一个原因是,操作员

BigIntegerNumber operator+ (BigIntegerNumber row2)

不是

覆盖
virtual CharRow operator+ (CharRow row2)

但它是重载(隐藏原始运算符而不是覆盖它)。

要使它成为覆盖,函数签名必须相同。即相同类型的参数(CharRow而不是BigIntegerNumber,最好通过const ref而不是值传递),以及相同或协变的返回类型。这些都不符合。

这样的事情有时通过使用“常规”虚函数来完成,其中接口引用作为参数,并通过调用这样的函数来实现非虚拟运算符。

在这种情况下,主要问题是返回参数,因为您无法将返回类型定义为按值CharRow并实际返回BigIntegerNumber(它将被切片为返回类型)。 operator +=可能会更幸运,它可以返回对自身的引用,从而能够以多态方式工作。

operator +=的示例(返回值类型没有问题):

#include <iostream>
using namespace std;

struct Base
{
    virtual Base& operator +=(const Base& other);  // takes Derived as well for the virtual calls
};


struct Derived: Base
{
    Derived& operator +=(const Base& other);  // override - called via virtual
    Derived& operator +=(const Derived& other); // overload - not called via virtual
                                                // remove to always call the polymorphic version
};

Base& Base::operator +=(const Base& other)
{
    cout << "Base::operator +=(Base)";
    // beware this is slow!
    const Derived* d = dynamic_cast<const Derived*>(&other);
    if (d)
        cout << " - called with Derived";
    else
        cout << " - called with Base";
    cout << endl;
    return *this;
}

Derived& Derived::operator +=(const Base& other)
{
    cout << "Derived::operator +=(Base)";
    // beware this is slow!
    const Derived* d = dynamic_cast<const Derived*>(&other);
    if (d)
        cout << " - called with Derived";
    else
        cout << " - called with Base";
    cout << endl;
    return *this;
}

Derived& Derived::operator +=(const Derived& other)
{
    cout << "Derived::operator +=(Derived)" << endl;
    return *this;
}

int main()
{
    Derived d1, d2;
    Base b, b0;
    Base& b1 = d1;
    Base& b2 = d2;

    d1 += d2;  // Derived::operator +=(Derived)
    b1 += d2;  // Derived::operator +=(Base) - called with Derived
    d1 += b1;  // Derived::operator +=(Base) - called with Derived
    b1 += b2;  // Derived::operator +=(Base) - called with Derived
    b += d2;   // Base::operator +=(Base) - called with Derived
    d1 += b;   // Derived::operator +=(Base) - called with Base
    b += b0;   // Base::operator +=(Base) - called with Base
    b1 += b;   // Derived::operator +=(Base) - called with Base

    return 0;
}

对于operator +,按值传递的结果类型是问题。但是,在C ++中仍然不是不可能的,但是你需要使用某种包装器。这种包装器的一个例子:

#include <iostream>
#include <memory>
using namespace std;


struct Base;
struct Derived;

class BaseWrapper
{
    shared_ptr<Base> _obj;
public:
    explicit BaseWrapper(const shared_ptr<Base>& obj) : _obj(obj)
    {}
    template<class RESULT_T>
    operator RESULT_T()
    {
        // throws if type not correct
        return dynamic_cast<RESULT_T&>(*_obj);
    }
    Base& operator +=(const Base& other);
    BaseWrapper operator +(const Base& other) const;
};

struct Base
{
    virtual Base& operator +=(const Base& other);  // takes Derived as well for the virtual calls
    BaseWrapper operator +(const Base& other) const;
private:
    virtual shared_ptr<Base> copy() const
    {
        return make_shared<Base>(*this);
    }
};


struct Derived : Base
{
    Derived& operator +=(const Base& other);  // override - called via virtual
private:
    virtual shared_ptr<Base> copy() const
    {
        return make_shared<Derived>(*this);
    }
};

Base& BaseWrapper::operator += (const Base& other)
{
    return *_obj += other;
}

BaseWrapper BaseWrapper::operator +(const Base& other) const
{
    return *_obj + other;
}

BaseWrapper Base::operator +(const Base& other) const
{
    BaseWrapper result(copy());
    result += other;
    return result;
}

int main()
{
    Derived d1, d2;
    Base b, b0;
    Base& b1 = d1;
    Base& b2 = d2;

    b = b1 + b2;  // add Derived + Derived, result is Derived (typed Base)
    b = b0 + d1;  // add Base + Derived, result is Base

    // d1 = b0 + d1;  // add Base + Derived, result is Base, throws bad_cast (cannot cast to Derived)

    d1 = b1 + b2;  // add Derived + Derived, result is Derived

    return 0;
}

也就是说,BaseWrapper可用于按值返回多态类型,并转换为原始类型。但请注意,在这种情况下,涉及内存分配。

答案 1 :(得分:-1)

如果你想在BigIntegerNumber :: operator +()中调用CharRow :: operator +(),你可以这样做:

rI."REFCL||'_TEST'"
相关问题