Yo, como muchos programadores antes que yo, me estoy arrancando el pelo escribiendo el derecho de paso-matriz-clase-en-C++. Nunca he hecho una sobrecarga al operador muy grave y esto está causando problemas. Esencialmente, al pasar por¿Cómo hago para sobrecargar a los operadores de C++ para permitir el encadenamiento?
Esto es lo que llamo causar los problemas.
cMatrix Kev = CT::cMatrix::GetUnitMatrix(4, true);
Kev *= 4.0f;
cMatrix Baz = Kev;
Kev = Kev+Baz; //HERE!
Lo que parece estar sucediendo de acuerdo con el depurador es que se añaden Kev y Baz pero entonces se pierde el valor y cuando se trata de reasignar a Kev, la memoria es sólo sus valores por defecto poco fiables. ¿Cómo sobrecargo mis operadores para permitir esta declaración? Mi código (reducido) está debajo.
//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;
}
Mi objetivo en Esta etapa consiste en seguir con la versión estándar de C++ y evitar vincular cualquier otra librería si es posible. ¡Boost es útil, pero también un poco bestial! – User2400
Prefiero implementar 'operator +' como no miembro. Entre otras ventajas, esto también permite que un compilador C++ 11 optimice la copia de un valor rf t argumento si lo pasa por valor. (Consulte mi respuesta.) – sbi
@fneep: Entiendo eso, pero aún debe echar un vistazo a Boost.Operator para comprender la forma canónica de implementar operadores. – Sebastian