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

时间:2022-09-02 12:36:21

i am writing a Matrix4 class for an OpenGL game:

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

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;
    }
};`

With the following class, i then create some variables and thest them in my main file:

使用下面的类,我然后在我的主文件中创建一些变量和它们:

//#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;
}

The problem is that, if i try the following operation:

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

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

i get the -107374176.000000 number as output, repeated 16 times, while storing the value in a variable:

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

sum = another + mat;

works fine. What could be the problem?

工作良好。可能是什么问题呢?

1 个解决方案

#1


Your overloaded operators are declared as returning references, however some of them are missing the return *this; statement (operator+=, operator-=, operator*=). Also, in the operators that return *this, you are doing it wrong. You make a copy to *this then return the copy. Bam, dangling reference. Example from your code:

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

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
}

So you should really return by value here. Moreover, binary operators are best implemented as friends. See Operator overloading for an excellent guide.

所以你应该在这里真正回报价值。此外,二元运算符最好实现为朋友。有关优秀指南,请参阅操作员重载。

#1


Your overloaded operators are declared as returning references, however some of them are missing the return *this; statement (operator+=, operator-=, operator*=). Also, in the operators that return *this, you are doing it wrong. You make a copy to *this then return the copy. Bam, dangling reference. Example from your code:

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

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
}

So you should really return by value here. Moreover, binary operators are best implemented as friends. See Operator overloading for an excellent guide.

所以你应该在这里真正回报价值。此外,二元运算符最好实现为朋友。有关优秀指南,请参阅操作员重载。