在我的 Matrix4 class 中使用一些用户定义的运算符的操作返回高值非常高的值

Operations with some user-defined operators in my Matrix4 class are returning high values very high values

我正在为 OpenGL 游戏编写 Matrix4 class:

static class Matrix4
{
private:
    float matrix[16];
    Matrix4 Identity()
    {
        matrix[1] = matrix[2] =
            matrix[3] = matrix[4] = matrix[6] =
            matrix[7] = matrix[8] = matrix[9] =
            matrix[11] = matrix[12] = matrix[13] = matrix[14] = 0.f;
        matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.f;
        return *this;
    }

public:
    Matrix4() { Identity(); };
    Matrix4(float vals[16])
    {
        matrix[0] = vals[0]; matrix[1] = vals[1]; matrix[2] = vals[2]; matrix[3] = vals[3];
        matrix[4] = vals[4]; matrix[5] = vals[5]; matrix[6] = vals[6]; matrix[7] = vals[7];
        matrix[8] = vals[8]; matrix[9] = vals[9]; matrix[10] = vals[10]; matrix[11] = vals[11];
        matrix[12] = vals[12]; matrix[13] = vals[13]; matrix[14] = vals[14]; matrix[15] = vals[15];
    }
    Matrix4(Vector4 vals[4])
    {
        matrix[0] = vals[0].GetX(); matrix[1] = vals[0].GetY(); matrix[2] = vals[0].GetZ(); matrix[3] = vals[0].GetW();
        matrix[4] = vals[1].GetX(); matrix[5] = vals[1].GetY(); matrix[6] = vals[1].GetZ(); matrix[7] = vals[1].GetW();
        matrix[8] = vals[2].GetX(); matrix[9] = vals[2].GetY(); matrix[10] = vals[2].GetZ(); matrix[11] = vals[2].GetW();
        matrix[12] = vals[3].GetX(); matrix[13] = vals[3].GetY(); matrix[14] = vals[3].GetZ(); matrix[15] = vals[3].GetW();
    }

    //OPERATOR DEFINITIONS
    //STUDY THE operator<< SHIT

    static friend std::ostream& operator<< (std::ostream& os, const Matrix4& other)
    {
        std::string final = "_____________________________________________\n| " + std::to_string(other.matrix[0]) + " " + std::to_string(other.matrix[1]) + " " + std::to_string(other.matrix[2]) + " " + std::to_string(other.matrix[3]) + " " + " |" + "\n" +
            "| " + std::to_string(other.matrix[4]) + " " + std::to_string(other.matrix[5]) + " " + std::to_string(other.matrix[6]) + " " + std::to_string(other.matrix[7]) + " " + " |" + "\n" +
            "| " + std::to_string(other.matrix[8]) + " " + std::to_string(other.matrix[9]) + " " + std::to_string(other.matrix[10]) + " " + std::to_string(other.matrix[11]) + " " + " |" + "\n" +
            "| " + std::to_string(other.matrix[12]) + " " + std::to_string(other.matrix[13]) + " " + std::to_string(other.matrix[14]) + " " + std::to_string(other.matrix[15]) + " " + " |";
        os.write(final.c_str(), final.size());
        return os;
    }

    Matrix4& operator+=(const Matrix4& other)
    {
        this->matrix[0] += other.matrix[0]; this->matrix[1] += other.matrix[1]; this->matrix[2] += other.matrix[2]; this->matrix[3] += other.matrix[3];
        this->matrix[4] += other.matrix[4]; this->matrix[5] += other.matrix[5]; this->matrix[6] += other.matrix[6]; this->matrix[7] += other.matrix[7];
        this->matrix[8] += other.matrix[8]; this->matrix[9] += other.matrix[9]; this->matrix[10] += other.matrix[10]; this->matrix[11] += other.matrix[11];
        this->matrix[12] += other.matrix[12]; this->matrix[13] += other.matrix[13]; this->matrix[14] += other.matrix[14]; this->matrix[15] += other.matrix[15];
    }

    Matrix4& operator-=(const Matrix4& other)
    {
        this->matrix[0] -= other.matrix[0]; this->matrix[1] -= other.matrix[1]; this->matrix[2] -= other.matrix[2]; this->matrix[3] -= other.matrix[3];
        this->matrix[4] -= other.matrix[4]; this->matrix[5] -= other.matrix[5]; this->matrix[6] -= other.matrix[6]; this->matrix[7] -= other.matrix[7];
        this->matrix[8] -= other.matrix[8]; this->matrix[9] -= other.matrix[9]; this->matrix[10] -= other.matrix[10]; this->matrix[11] -= other.matrix[11];
        this->matrix[12] -= other.matrix[12]; this->matrix[13] -= other.matrix[13]; this->matrix[14] -= other.matrix[14]; this->matrix[15] -= other.matrix[15];
    }

    Matrix4& operator*=(float scale)
    {
        this->matrix[0] *= scale; this->matrix[1] *= scale; this->matrix[2] *= scale; this->matrix[3] *= scale;
        this->matrix[4] *= scale; this->matrix[5] *= scale; this->matrix[6] *= scale; this->matrix[7] *= scale;
        this->matrix[8] *= scale; this->matrix[9] *= scale; this->matrix[10] *= scale; this->matrix[11] *= scale;
        this->matrix[12] *= scale; this->matrix[13] *= scale; this->matrix[14] *= scale; this->matrix[15] *= scale;
    }

    Matrix4& operator*=(Vector3& other)
    {
        this->matrix[0] *= other.GetX(); this->matrix[1] *= other.GetX(); this->matrix[2] *= other.GetX(); this->matrix[3] *= 1;
        this->matrix[4] *= other.GetY(); this->matrix[5] *= other.GetY(); this->matrix[6] *= other.GetY(); this->matrix[7] *= 1;
        this->matrix[8] *= other.GetZ(); this->matrix[9] *= other.GetZ(); this->matrix[10] *= other.GetZ(); this->matrix[11] *= 1;
        return *this;
    }

    Matrix4& operator*= (Vector4& other)
    {
        this->matrix[0] *= other.GetX(); this->matrix[1] *= other.GetX(); this->matrix[2] *= other.GetX(); this->matrix[3] *= other.GetX();
        this->matrix[4] *= other.GetY(); this->matrix[5] *= other.GetY(); this->matrix[6] *= other.GetY(); this->matrix[7] *= other.GetY();
        this->matrix[8] *= other.GetZ(); this->matrix[9] *= other.GetZ(); this->matrix[10] *= other.GetZ(); this->matrix[11] *= other.GetZ();
        this->matrix[12] *= other.GetW(); this->matrix[13] *= other.GetW(); this->matrix[14] *= other.GetW(); this->matrix[15] *= other.GetW();
        return *this;
    }

    Matrix4& operator= (Matrix4& other)
    {
        this->matrix[0] = other.matrix[0]; this->matrix[1] = other.matrix[1]; this->matrix[2] = other.matrix[2]; this->matrix[3] = other.matrix[3];
        this->matrix[4] = other.matrix[4]; this->matrix[5] = other.matrix[5]; this->matrix[6] = other.matrix[6]; this->matrix[7] = other.matrix[7];
        this->matrix[8] = other.matrix[8]; this->matrix[9] = other.matrix[9]; this->matrix[10] = other.matrix[10]; this->matrix[11] = other.matrix[11];
        this->matrix[12] = other.matrix[12]; this->matrix[13] = other.matrix[13]; this->matrix[14] = other.matrix[14]; this->matrix[15] = other.matrix[15];
        return *this;
    }


    //BUG: You need to put the matrix in a variable, otherwise you wil gett strange values
    Matrix4& operator+(const Matrix4& other)
    {
        Matrix4 tmp = *this;
        for (int i = 0; i < 16; i++)
        {
            tmp.matrix[i] += other.matrix[i];
        }
        return tmp;
    }

    Matrix4& operator-(const Matrix4& other)
    {
        Matrix4 tmp = *this;
        for (int i = 0; i < 16; i++)
        {
            tmp.matrix[i] -= other.matrix[i];
        }
        return tmp;
    }

    Matrix4& operator*(Vector3& other)
    {
        Matrix4 tmp = *this;
        tmp.matrix[0] *= other.GetX(); tmp.matrix[1] *= other.GetX(); tmp.matrix[2] *= other.GetX(); tmp.matrix[3] *= 1;
        tmp.matrix[4] *= other.GetY(); tmp.matrix[5] *= other.GetY(); tmp.matrix[6] *= other.GetY(); tmp.matrix[7] *= 1;
        tmp.matrix[8] *= other.GetZ(); tmp.matrix[9] *= other.GetZ(); tmp.matrix[10] *= other.GetZ(); tmp.matrix[11] *= 1;
        return tmp;
    }

    Matrix4& operator*(Vector4& other)
    {
        Matrix4 tmp = *this;
        tmp.matrix[0] *= other.GetX(); tmp.matrix[1] *= other.GetX(); tmp.matrix[2] *= other.GetX(); tmp.matrix[3] *= other.GetX();
        tmp.matrix[4] *= other.GetY(); tmp.matrix[5] *= other.GetY(); tmp.matrix[6] *= other.GetY(); tmp.matrix[7] *= other.GetY();
        tmp.matrix[8] *= other.GetZ(); tmp.matrix[9] *= other.GetZ(); tmp.matrix[10] *= other.GetZ(); tmp.matrix[11] *= other.GetZ();
        tmp.matrix[12] *= other.GetW(); tmp.matrix[13] *= other.GetW(); tmp.matrix[14] *= other.GetW(); tmp.matrix[15] *= other.GetW();
        return tmp;
    }

    //WIP: CREATE BINARY OPERATORS

    //Index goes from 0 to 3
    void SetCol(unsigned int index, float f1, float f2, float f3, float f4)
    {
        matrix[index * 4] = f1;
        matrix[index * 4 + 1] = f2;
        matrix[index * 4 + 2] = f3;
        matrix[index * 4 + 3] = f4;
    }

    //Index goes from 0 to 3
    void SetCol(unsigned int index, const float vals[])
    {
        matrix[index * 4] = vals[0];
        matrix[index * 4 + 1] = vals[1];
        matrix[index * 4 + 2] = vals[2];
        matrix[index * 4 + 3] = vals[3];
    }

    //Index goes from 0 to 3
    void SetCol(unsigned int index, Vector4 val)
    {
        matrix[index * 4] = val.GetX();
        matrix[index * 4 + 1] = val.GetY();
        matrix[index * 4 + 2] = val.GetZ();
        matrix[index * 4 + 3] = val.GetW();
    }

    Matrix4 MultiplyByVec3Floats (float x, float y, float z)
    {
        this->matrix[0] *= x; this->matrix[1] *= x; this->matrix[2] *= x; this->matrix[3] *= 1;
        this->matrix[4] *= y; this->matrix[5] *= y; this->matrix[6] *= y; this->matrix[7] *= 1;
        this->matrix[8] *= z; this->matrix[9] *= z; this->matrix[10] *= z; this->matrix[11] *= 1;
    }

    Matrix4 MultiplyByVec4Floats(float x, float y, float z, float w)
    {
        this->matrix[0] *= x; this->matrix[1] *= x; this->matrix[2] *= x; this->matrix[3] *= w;
        this->matrix[4] *= y; this->matrix[5] *= y; this->matrix[6] *= y; this->matrix[7] *= w;
        this->matrix[8] *= z; this->matrix[9] *= z; this->matrix[10] *= z; this->matrix[11] *= w;
        this->matrix[12] *= x; this->matrix[13] *= y; this->matrix[14] *= z; this->matrix[15] *= w;
    }
};`

使用以下 class,然后我创建一些变量并将它们放在我的主文件中:

//#define TEST_VECTORS
#define TEST_MATRIX

#include <iostream>
#include <sdl/SDL.h>
#include<gl\glew.h>
#include <ostream>
#include <string>

#include "Game.h"
#include "gmath.h"



using namespace std;

int main(int argc, char* argv[])
{
#ifdef TEST_VECTORS
gmath::Vector3 vTestVector(5, 5, 5);
gmath::Vector3 vAnotherVector(1, 1, 1);
gmath::Vector3 vZeroVector = gmath::Vector3::Zero();
cout << vTestVector.Length() << endl;

cout << vTestVector + vAnotherVector << endl;

cout << vTestVector - vAnotherVector << endl;

cout << gmath::Vector3::Distance(vTestVector, vAnotherVector) << endl;

cout << vTestVector.Normalized() << endl;

cout << (vTestVector == vTestVector) << endl;

cout << gmath::Vector3::Dot(vTestVector, vAnotherVector) << endl;

cout << gmath::Vector3::Cross(vTestVector, vAnotherVector) << endl;
#endif

#ifdef TEST_MATRIX
gmath::Matrix4 mat;
float vals[] = { 1.f, 2.f, 3.f, 4.f };
mat.SetCol(1, vals);

gmath::Vector4 testVec(1.f, 4.f, 2.f, 1.f);
mat.SetCol(3, testVec);
mat.SetCol(0, 1.f, 5.f, 35.f, 6.f);

gmath::Matrix4 another;
another = mat;
std::cout << mat << std::endl;

std::cout << another << std::endl;

gmath::Matrix4 sum = another + mat;

cout << sum << std::endl;
gmath::Matrix4 prod = sum*testVec;
cout << prod << endl;
mat = gmath::Matrix4();
cout << mat << endl;

#endif
Game* g = new Game("MyGLTest", 800, 600, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
while (g->isGameRunning())
{
    g->Update();
    g->HandleInput();
}

return 0;
}

问题是,如果我尝试以下操作:

cout << another + mat << std::endl;

我得到 -107374176.000000 数字作为输出,重复 16 次,同时将值存储在变量中:

sum = another + mat;

工作正常。 可能是什么问题?

您的重载运算符被声明为 returning 引用,但是其中一些缺少 return *this; 语句(operator+=operator-=operator*= ).另外,在 return *this 的运算符中,你做错了。您将副本复制到 *this,然后复制到 return。砰,悬垂的参考。您的代码示例:

Matrix4& operator-(const Matrix4& other)
{
    Matrix4 tmp = *this; // this is a local object, cease to exist at function exit
    for (int i = 0; i < 16; i++)
    {
        tmp.matrix[i] -= other.matrix[i];
    }
    return tmp; // here you're done, return a reference to a local object
}

所以你真的应该 return 按这里的值。此外,二元运算符最好作为朋友来实现。请参阅 Operator overloading 以获得出色的指南。