-
One time, my program runs and shows expected output, and sometime it don’t (it compiles without any errors). Try-Catch doesen’t seem to affect on this random output.
-
v3f is a simple class that holds 3 floats: x,y,z and some basic math operations on them (all of them work perfectly fine)
v3f calculate_normal(v3f a, v3f b, v3f c);
- "calculate_normal" is just a simple multiplication and subtraction function that returns v3f, AND when it "decides" to work it gives expected output.
int main()
{
lv::v3f c(-0.5, -0.5, 0);
lv::v3f b(0, .5f, 0);
lv::v3f a(0.5, -0.5, 0);
/* if I add here
v3f d = a - b;
*/ it works !
lv::v3f normal;
std::cout << "1\n";
normal = lv::calculate_normal(a, b, c);
std::cout << "2\n";
std::cout << normal.x << " " << normal.y << " " << normal.z << std::endl;
std::cout << "3\n";
return 0;
}
I cout’ed 1, 2 and 3 to see when program breaks and it’s sometimes outputting all:
output:
1
2
0 0 1
3
And sometimes it stops on "1" (before calculating normal)
output:
1
// - - - - - - - - - - - - - - "Vector3.h"
#ifndef _LV_VECTOR_3_H_
#define _LV_VECTOR_3_H_
namespace lv{
template <class T>
class Vector3
{
public:
T x, y, z;
Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z){}
float length()
{
return sqrt( pow(x, 2) + pow(y, 2) + pow(z, 2) );
}
Vector3<T> normal()
{
float l = length();
return Vector3<T>(x/l, y/l, z/l);
}
void normalize()
{
float l = length();
x /= l;
y /= l;
z /= l;
}
Vector3<T>& operator += (const Vector3<T>& o)
{
this->x += o.x;
this->y += o.y;
this->z += o.z;
return *this;
}
Vector3<T>& operator -= (const Vector3<T>& o)
{
this->x -= o.x;
this->y -= o.y;
this->z -= o.z;
return *this;
}
Vector3<T>& operator *= (const Vector3<T>& o)
{
this->x *= o.x;
this->y *= o.y;
this->z *= o.z;
return *this;
}
Vector3<T>& operator /= (const Vector3<T>& o)
{
this->x /= o.x;
this->y /= o.y;
this->z /= o.z;
return *this;
}
friend Vector3<T>& operator + (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x + p.x;
tmp->y = o.y + p.y;
tmp->z = o.z + p.z;
return *tmp;
}
friend Vector3<T>& operator - (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x - p.x;
tmp->y = o.y - p.y;
tmp->z = o.z - p.z;
return *tmp;
}
friend Vector3<T>& operator / (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x / p.x;
tmp->y = o.y / p.y;
tmp->y = o.z / p.z;
return *tmp;
}
friend Vector3<T>& operator * (const Vector3<T>& o, const Vector3<T> p)
{
Vector3<T>* tmp;
tmp->x = o.x * p.x;
tmp->y = o.y * p.y;
tmp->z = o.z * p.z;
return *tmp;
}
friend Vector3<T>& operator * (const Vector3<T>&o, float p)
{
Vector3<T>* tmp;
tmp->x = o.x * p;
tmp->y = o.y * p;
tmp->z = o.z * p;
return *tmp;
}
friend Vector3<T>& operator / (const Vector3<T>&o, float p)
{
Vector3<T>* tmp;
tmp->x = o.x / p;
tmp->y = o.y / p;
tmp->z = o.z / p;
return *tmp;
}
};
#define v3f Vector3<float>
#define v3i Vector3<int>
#define v3d Vector3<double>
#define v3ui Vector3<unsigned int>
}; // L V
#endif
// - - - - - - - - - - - - - - "Vector.h"
#ifndef _LV_VECTOR_H_
#define _LV_VECTOR_H_
#include "Vector2.h"
#include "Vector3.h"
#include "Vector4.h"
#endif
// - - - - - - - - - - - - - - "Utils.h"
#ifndef _LV_UTILS_H_
#define _LV_UTILS_H_
#include "Vector.h"
namespace lv {
v3f calculate_normal(v3f a, v3f b, v3f c)
{
std::cout << "a\n";
v3f u = b - a;
v3f v = c - a;
std::cout << "b\n";
v3f n;
n.x = u.y * v.z - u.z * v.y;
n.y = u.z * v.x - u.x * v.z;
n.z = u.x * v.y - u.y * v.x;
std::cout << "c\n";
return n;
}
}; // L V
#endif
// - - - - - - - - - - - - - - "main.cpp"
#include <iostream>
#include "Liviana/Math/Utils.h"
int main()
{
lv::v3f c(-0.5, -0.5, 0);
lv::v3f b(0, .5f, 0);
lv::v3f a(0.5, -0.5, 0);
lv::v3f normal;
std::cout << "1\n";
normal = lv::calculate_normal(a, b, c);
std::cout << "2\n";
std::cout << normal.x << " " << normal.y << " " << normal.z << std::endl;
std::cout << "3\n";
return 0;
}
>Solution :
Only the mutating operators should return references. The other operators should return values.
OK:
Vector3<T>& operator += (const Vector3<T>& o)
Not ok:
friend Vector3<T>& operator + (const Vector3<T>& o, const Vector3<T> p)
The above is not ok, because…what are you going to return a reference to? 1 + 2 is neither 1 nor 2. It’s something else. You’ll need storage for the result (a Vector3) and you’ll need to return it by value.
friend Vector3<T> operator + (const Vector3<T>& o, const Vector3<T> p) {
Vector3<T> tmp;
tmp.x = o.x + p.x;
tmp.y = o.y + p.y;
tmp.z = o.z + p.z;
return tmp;
}
Note the & is gone from the return type.