简体   繁体   English

如何重载C ++运算符以允许链接?

[英]How do I go about overloading C++ operators to allow for chaining?

I, like so many programmers before me, am tearing my hair out writing the right-of-passage-matrix-class-in-C++. 就像我之前的许多程序员一样,我正在试着用C ++编写通道矩阵类。 I have never done very serious operator overloading and this is causing issues. 我从未做过非常严重的运算符重载,这导致了问题。 Essentially, by stepping through 基本上,通过单步执行

This is what I call to cause the problems. 这就是我所说的导致问题的原因。

    cMatrix Kev = CT::cMatrix::GetUnitMatrix(4, true);
    Kev *= 4.0f;
    cMatrix Baz = Kev;
    Kev = Kev+Baz;  //HERE!

What seems to be happening according to the debugger is that Kev and Baz are added but then the value is lost and when it comes to reassigning to Kev, the memory is just its default dodgy values. 根据调试器似乎正在发生的事情是添加了Kev和Baz,但随后该值丢失,当重新分配给Kev时,内存只是其默认的狡猾值。 How do I overload my operators to allow for this statement? 如何重载我的运算符以允许此语句? My (stripped down) code is below. 我的(精简版)代码如下。

//header
class cMatrix
{
private:
    float* _internal;
    UInt32 _r;
    UInt32 _c;
    bool _zeroindexed;

    //fast, assumes zero index, no safety checks
    float cMatrix::_getelement(UInt32 r, UInt32 c)
    {
        return _internal[(r*this->_c)+c];
    }

    void cMatrix::_setelement(UInt32 r, UInt32 c, float Value)
    {
        _internal[(r*this->_c)+c] = Value;
    }

public:
    cMatrix(UInt32 r, UInt32 c, bool IsZeroIndexed);
    cMatrix( cMatrix& m);
    ~cMatrix(void);

    //operators
    cMatrix& operator + (cMatrix m);
    cMatrix& operator += (cMatrix m);
    cMatrix& operator = (const cMatrix &m);
};

//stripped source file
cMatrix::cMatrix(cMatrix& m)
{
    _r = m._r;
    _c = m._c;
    _zeroindexed = m._zeroindexed;
    _internal = new float[_r*_c];

    UInt32 size = GetElementCount();

    for (UInt32 i = 0; i < size; i++)
    {
        _internal[i] = m._internal[i];
    }
}

cMatrix::~cMatrix(void)
{
    delete[] _internal;
}
cMatrix& cMatrix::operator+(cMatrix m) 
{
    return cMatrix(*this) += m;
}

cMatrix& cMatrix::operator*(float f) 
{
    return cMatrix(*this) *= f;
}

cMatrix& cMatrix::operator*=(float f) 
{
    UInt32 size = GetElementCount();

    for (UInt32 i = 0; i < size; i++)
    {
        _internal[i] *= f;
    }

    return *this;
}

cMatrix& cMatrix::operator+=(cMatrix m) 
{
    if (_c != m._c || _r != m._r)
    {
        throw new cCTException("Cannot add two matrix classes of different sizes.");
    }
    if (!(_zeroindexed && m._zeroindexed))
    {
        throw new cCTException("Zero-Indexed mismatch.");
    }

    for (UInt32 row = 0; row < _r; row++)
    {
        for (UInt32 column = 0; column < _c; column++)
        {
            float Current = _getelement(row, column) + m._getelement(row, column);
            _setelement(row, column, Current);
        }
    }

    return *this;
}

cMatrix& cMatrix::operator=(const cMatrix &m) 
{
    if (this != &m) 
    {
        _r = m._r;
        _c = m._c;
        _zeroindexed = m._zeroindexed;

        delete[] _internal;

        _internal = new float[_r*_c];

        UInt32 size = GetElementCount();

        for (UInt32 i = 0; i < size; i++)
        {
            _internal[i] = m._internal[i];
        }
    }
    return *this;
  }

Your operators + and * must return by value, not by reference. 您的运算符+和*必须按值返回,而不是按引用返回。 You're returning a temporary variable by reference. 您将通过引用返回临时变量。 Also, you're arguments are passed by value when it should be a const reference: 此外,当参数应为const引用时,您的参数将按值传递:

cMatrix cMatrix::operator+(cMatrix const& m) 
{
    cMatrix matrix(*this);
    matrix += m;
    return matrix;
}

cMatrix cMatrix::operator*(float f) 
{
    cMatrix matrix(*this);
    matrix *= m;
    return matrix;
}

You should take a look at Boost.Operators . 你应该看看Boost.Operators This would let you implement only operator*= and operator+= and automatically provide correct implementations for operator+ and operator* . 这将允许您仅实现operator*=operator+=并自动为operator+operator*提供正确的实现。

PS: If you implement your matrix class just for the learning experience, don't hesitate to look at other implementations like the Matrix Template Library . PS:如果您只是为了学习体验而实现矩阵类,请不要犹豫,看看像Matrix模板库这样的其他实现。

PPS: If you don't want to use boost, or if you just want to understand the best practice, take a look at Boost.Operator and do what they do. PPS:如果您不想使用boost,或者您只是想了解最佳实践,请查看Boost.Operator并执行他们的操作。

IMO the canonical form of overloading addition is this: IMO规范形式的重载添加是这样的:

class X {
public:
  X& operator+=(const X& rhs) { /*add rhs to *this*/ }
};

inline X operator+(X lhs, const X& rhs) {lhs+=rhs; return lhs;}

The same goes for - , * , / , where applicable. 适用的情况与-*/相同。

Note that + returns a copy, not a reference. 请注意, +返回副本,而不是引用。 That's important, because A+B creates a new value, so it cannot return a reference to an existing one. 这很重要,因为A+B创建了一个新值,因此它不能返回对现有值的引用。
Also, it is a free function. 此外,它是一个免费的功能。 IMO it's best to implement those of the binary operators which can be implement either as a member or as a free function as free functions, if they treat their operands symmetrically (as does + ), and as member functions, if they treat their operands asymmetrically (as += , which changes its left argument. If you implement operator+ as a member, you will have to make the function const ( X operator+(const X& rhs) const ), so that it can be invoked for constant elements on the left side. IMO最好实现二元运算符的那些,它们既可以作为成员实现,也可以作为自由函数实现,如果它们对称地处理它们的操作数(如同+ ),并且作为成员函数,如果它们不对称地处理它们的操作数(因为+= ,它改变了它的左参数。如果你实现operator+作为成员,你将不得不使函数constX operator+(const X& rhs) const ),以便可以为左边的常量元素调用它侧。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM