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

Use*_*400 5 c++ operator-overloading matrix

就像我之前的许多程序员一样,我正在试着用C++编写通道矩阵类.我从未做过非常严重的运算符重载,这导致了问题.基本上,通过单步执行

这就是我所说的导致问题的原因.

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

根据调试器似乎正在发生的事情是添加了Kev和Baz,但随后该值丢失,当重新分配给Kev时,内存只是其默认的狡猾值.如何重载我的运算符以允许此语句?我的(精简版)代码如下.

//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;
  }
Run Code Online (Sandbox Code Playgroud)

Seb*_*ian 10

您的运算符+和*必须按值返回,而不是按引用返回.您将通过引用返回临时变量.此外,当参数应为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;
}
Run Code Online (Sandbox Code Playgroud)

你应该看看Boost.Operators.这将让你实现只operator*=operator+=并自动提供正确的实现operator+operator*.

PS:如果您只是为了学习体验而实现矩阵类,请不要犹豫,看看像Matrix模板库这样的其他实现.

PPS:如果您不想使用boost,或者您只是想了解最佳实践,请查看Boost.Operator并执行他们的操作.


sbi*_*sbi 8

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;}
Run Code Online (Sandbox Code Playgroud)

这同样适用于-,*,/,如适用.

请注意,+返回副本,而不是引用.这很重要,因为它A+B创建了一个新值,因此它无法返回对现有值的引用.
此外,它是一个免费的功能.IMO最好实现二元运算符的那些,它们既可以作为成员实现,也可以作为自由函数实现,如果它们对称地处理它们的操作数(如同+),作为成员函数,如果它们不对称地处理它们的操作数( as +=,更改其左参数.如果实现operator+为成员,则必须创建function const(X operator+(const X& rhs) const),以便可以为左侧的常量元素调用它.