I have a simple vector class, and I'm trying to overload the operator+ to add vectors. When it didn't work in my main program, I created a new project and stripped it down to the bare minimum, and it still didn't work.
Bare minimum code:
main.cpp
#include "vector3f.h"
int main()
{
Vector3f* a = new Vector3f();
Vector3f* b = new Vector3f();
Vector3f* c = a + b;
}
vector.h
#ifndef __VECTOR3F_H__
#define __VECTOR3F_H__
class Vector3f
{
public:
float x;
float y;
float z;
Vector3f();
Vector3f(float x, float y, float z);
~Vector3f();
Vector3f operator+(const Vector3f& rhs);
};
#endif
vector.cpp
#include "vector3f.h"
Vector3f::Vector3f()
{
x = 0;
y = 0;
z = 0;
}
Vector3f::Vector3f(float x, float y, float z)
{
this->x = x;
this->y = y;
this->z = z;
}
Vector3f::~Vector3f()
{
}
Vector3f Vector3f::operator+(const Vector3f& rhs)
{
return Vector3f(x + rhs.x, y + rhs.y, z + rhs.z);
}
Here is the compile error:
main.cpp: In function 'int main()':
main.cpp:7: error: invalid operands of types 'Vector3f*' and 'Vector3f*' to binary 'operator+'
main.cpp line 7 is Vector3f* c = a + b;.
So my question, as is expected on Stack Overflow, is: what am I doing wrong?
Side note: I have a very lame IDE and the problem may be a faulty compiler, though I don't expect this to be the case.
Any help is appreciated. Thanks in advance!!
You dynamically allocated your Vectors, and the + operator is not defined for pointers to vectors.
So you need to change:
Vector3f* a = new Vector3f();
Vector3f* b = new Vector3f();
//... assigning of and b
Vector3f* c = a + b;
To
Vector3f* a = new Vector3f();
Vector3f* b = new Vector3f();
Vector3f* c = new Vector3f();
*c = *a + *b;
I'm surprised this hasn't been said, but why are you using pointers at all?
Vector3f a;
Vector3f b;
Vector3f c = a + b;
No more trying to add pointers. No more awkward syntax. No more memory leaks.
Apart from this, you have some other things you should change:
__VECTOR3F_H__ is a reserved identifier.
You should get used to using constructor initializer lists (: x(0), y(0), z(0) and : x(x), y(y), z(z)) instead of assigning to data members after they've already been initialized.
You don't need a destructor here, as one will be provided for you.
operator+ should be implemented using operator+=, which you should also provide.
Try this ,
Vector3f c = *a + *b;
Now this will overload your operator else it was an pointer addition
You have overloaded objects not object pointers. Use this
Vector3f c = (*a) + (*b);
Related
I'm currently working on implementing a simple 2D vector class Vector2f in C++ using Visual Studio Community Edition 2019.
When I try to return a newly constructed one in a method, such as:
return Vector2f((this->x/sum),(this->y/sum);
I'm getting a hint:
no suitable copy constructor for Vector2f
and an on-compile error:
'return': cannot convert from 'Vector2f' to 'Vector2f'
I've rewritten the class from scratch a few times, and still seem to be getting the error. I don't understand, what exactly is going wrong?
Vector2f_struct.h
#pragma once
#ifndef PMP_VECTOR2F_STRUCT__H
#define PMP_VECTOR2F_STRUCT__H
namespace pmp
{
struct Vector2f
{
/* Elements */
float x;
float y;
/* Methods */
// Constructors & Destructor
Vector2f();
Vector2f(float i, float j);
Vector2f(Vector2f& og);
virtual ~Vector2f();
// Unary Operators
float magnitude();
Vector2f normal();
};
};
#endif
Vector2f_struct.cpp
#include "pmp_Vector2f_struct.h"
#ifndef PMP_VECTOR2F_STRUCT__CPP
#define PMP_VECTOR2F_STRUCT__CPP
/* Dependencies */
#include <math.h>
namespace pmp
{
Vector2f::Vector2f()
{
this->x = 0.0f;
this->y = 0.0f;
return;
};
Vector2f::Vector2f(float i, float j)
{
this->x = i;
this->y = j;
return;
};
Vector2f::Vector2f( Vector2f& og )
{
this->x = og.x;
this->y = og.y;
return;
};
Vector2f::~Vector2f()
{
this->x = 0.0f;
this->y = 0.0f;
return;
};
float Vector2f::magnitude()
{
float c2 = (this->x * this->x) + (this->y * this->y);
return sqrt(c2);
};
Vector2f Vector2f::normal()
{
float sum = this->x + this->y;
return Vector2f(this->x / sum, this->y / sum); // Error here.
};
};
#endif
The parameter of the copy constructor has a non-constant referenced type
Vector2f(Vector2f& og);
In the member function normal there is returned a temporary object that is copied. You may not bind a temporary object with a non-constant lvalue reference.
Redeclare the copy constructor like
Vector2f(const Vector2f& og);
Or just remove its explicit declaration. In this case the compiler generates it for you.
Pay attention to that return statements in the constructors and the destructor are redundant.
I'm new to C++ but I have a good programming background and I have been looking for function calls that don't need a reference object to a struct or class. The best referral to what I'm looking for is probably any of unity's classes where for instance Vector2.Distance can be used and it returns another Vector2 but Vector2 is the class!
#include <stdio.h>
#include <stdlib.h>
struct vector {
float x, y;
// only recently figured out you could do this
// instead of vector() {x = 0.0; y = 0.0} etc.
vector() : x(0.0), y(0.0) {}
vector(float _x, float _y) : x(_x), y(_y) {}
vector add(vector a, vector b) {
return vector(this->x + b.x, this->y + b.y);
}
};
int main() {
vector a = vector(2, 3);
vector b = vector(4, 4);
vector c = vector.add(a, b);
printf("%f, %f", c.x, c.y);
return 0;
}
// expected output from this function: 6, 7
The code above is an example of what I am wanting, so the reasoning behind what is happening is redundant, I know there is a vector class and I'm sure there is a much simpler way of doing this code in particular but this is the root functionality of what I want.
is this even possible in this language?
int main() {
vector a = vector(2, 3);
vector b = vector(4, 4);
this works: vector c = a.add(a, b);
this !works: vector c = vector.add(a, b);
printf("%f, %f", c.x, c.y);
return 0;
}
I am aware that this works but all im trying to do is get rid of needing the A reference in a.add();
I've tried static functions, looking into the std::functional thing, operation overloading but I might have misinterpreted something and came across a solution
Thanks in advance!
You can define static functions inside your classes.
#include <stdio.h>
#include <stdlib.h>
struct vector {
float x, y;
// only recently figured out you could do this
// instead of vector() {x = 0.0; y = 0.0} etc.
vector() : x(0.0), y(0.0) {}
vector(float _x, float _y) : x(_x), y(_y) {}
// add "static"
static vector add(vector a, vector b) {
return vector(a.x + b.x, a.y + b.y); // use correct object
}
};
int main() {
vector a = vector(2, 3);
vector b = vector(4, 4);
vector c = vector::add(a, b); // use :: instead of .
printf("%f, %f", c.x, c.y);
return 0;
}
I have a simple math vector struct
struct vec3d {
float x;
float y;
float z;
float w;
public:
vec3d(float a, float b, float c) { a = x; b = y; c = z; w = 1; }
vec3d() { x = 0; y = 0; z = 0; w = 1; }
};
With the following operation in a function (I am not using operator overloading)
vec3d vsubvector(vec3d& v1, vec3d& v2)
{
return vec3d(v1.x - v2.x, v1.y - v2.y,v1.z - v2.z);
}
I am using it inside the main function within a loop block like this
{
...
vec3d normal, line1, line2;
line1 = vsubvector(p[1], p[0]);
line2 = vsubvector(p[2], p[0]);
normal = vcrossproduct(line1, line2);
normal = vnormalise(normal);
...
}
Here p is an array of three vectors
Now while debugging, when I enter the block where the local variable is defined, line1.x, line1.y and line1.z are assigned a big signed float value (-107374176.0f) and they do not change after the subtract function is returned into them.
What is the reason that vsubvector function is not working?
vec3d(float a, float b, float c) { a = x; b = y; c = z; w = 1; }
Is assigning to the constructor arguments from the uninitialised member variables. Obviously wrong. You'd want to reverse the order of assignment.
Additionally, you should use the constructors initialization list to initialize members rather than the constructor body. Do this:
vec3d(float a, float b, float c) : x(a), y(b), z(c), w(1) { }
For basic types like ints or floats it makes little difference, but for user defined types it can make a big difference. It is wasteful to first let the constructor default initialize members and then subsequently assign to them in the constructor body. Also, for some types, doing so is not even possible, not all types support assignment so initialization is the only option.
Additionally, the default constructor vec3d() can delegate to the other constructor:
vec3d() : vec3d(0.f, 0.f, 0.f) {}
Relatively new to C++, I'm trying to learn using dynamic memory. In this case I'm using it to store member variables.
Quanternion.h -
#ifndef QUATERNION_H_
#define QUATERNION_H_
class Quaternion
{
private:
double* x = new double();
double* y = new double();
double* z = new double();
double* w = new double();
public:
Quaternion(double x, double y, double z, double w);
Quaternion(const Quaternion& q);
Quaternion& operator=(const Quaternion& q);
~Quaternion();
void setQ(double *_x, double *_y, double *_z, double *_w);
double * getX() { return x; }
double * getY() { return y; }
double * getz() { return z; }
double * getw() { return w; }
};
#endif
Quanternion.cpp -
#include "Quaternion.h"
Quaternion::Quaternion(double x, double y, double z, double w)
{
double*a = &x;
double*b = &y;
double*c = &z;
double*d = &w;
setQ(a,b,c,d);
}
Quaternion::Quaternion(const Quaternion & q)
{
this->x = q.x;
this->y = q.y;
this->z = q.z;
this->w = q.w;
}
Quaternion & Quaternion::operator=(const Quaternion & q)
{
if (this == &q)
{
return *this;
}
this->x = q.x;
this->y = q.y;
this->z = q.z;
this->w = q.w;
return *this;
}
Quaternion::~Quaternion()
{
}
void Quaternion::setQ(double *_x, double *_y, double *_z, double *_w)
{
this->x = _x;
this->y = _y;
this->z = _z;
this->w = _w;
}
When I create a Quaternion object and set the fields, and try and print one of the variables such as X by deallocating a pointer. I do not get the result I am expecting.
int main()
{
Quaternion q1(4, 9, 2, 5);
double*d = q1.getX();
cout << d << endl;
cout << *d << endl;
}
Example output -
00B1FB5C
6.26381e+148
Where am I going wrong?
Your code violates basic principles of managing raw pointers - you have no idea who owns them. The same pointer might be an allocated entity through new, or simply an address provided in the constructor. That makes owning those impossible - you can't write assignment operators or copy constructors (your current implmentation is wrong).
The more immediate problem is that you are remembering address of arguments in your 4-doubles constructor. This is the immediate cause for dangling pointer and undefined behavior.
If you want to learn how to use pointers, you need to read a book about it. If you simply need to use pointer-like semantics, use smart pointers.
I am pretty sure you're compiler gave you some warnings. In your constructor, you take the address of of the four initializer arguments x, y, z and w.
This is allowed, but only for using the address inside the constructor function itself. Because when the constructor function is done, these variables are not valid anymore, and therefore, pointers to them point to an invalid memory address (you don't know what's there anymore).
You have two options:
don't use pointers; in this class you don't need them. Copying a pointer takes just as much work as copying a double.
manage your pointers yourself. Create four new doubles in your constructor, and change their value. It might also be nice to look up refreneces.
I understand that you are trying to learn about pointers, but for this applications, pointers are really not necessary. And only make things slower. (Although not much).
you don't have implementation of setQ here
You are trying to pass by value and getting the address of the value in
Quaternion(double x, double y, double z, double w)
When You are trying to pass by value in Quaternion (double x, double y, double z, double w), You get the address of the value. After exit Quaternion (double x, double y, double z, double w) addresses are engaged in these variables are cleared away, and you are using is not your memory.
Lot's of year from last project in C++, I cannot remember/find how to do this.
Sample (pseudo code) :
MyClass
{
public :
float x;
float y;
float z;
}
main.cpp
void MyFunction(void)
{
MyClass *myclass = new MyClass();
float x = myclass->x;
//want I want :
float *xyz = myclass->xyz;
}
How to do this ?
Thank you very much and sorry for my poor english.
[EDITED]
It's only a concept now, but the goal, is near the vec4 class in GLSL (OpenGL Shader for GPU). Vec4 is a math vector class with four values (x, y, z, w). You can get/assign value like this sample :
vec4 vectorA = vec4(1.0, 1.0, 1.0, 1.0);
vectorA.x = 2.0;
vec2 vectorB = vectorA.xy;
vec3 vectorC = vectorA.xxx;
etc. (so : VectorC.x = 2.0, vectorC.y = 2.0, vectorC.z = 2.0)
Use unnamed structure:
union Vector
{
struct
{
float x;
float y;
float z;
};
float xyz[3];
};
Then you can access components without implicitly referencing containing structure:
int main()
{
Vector* vec = new Vector();
vec->x = 50;
vec->y = 30;
vec->xyz[2] = vec->xyz[0] + vec->xyz[1]; // vec->z == 80
delete vec;
return 0;
}
Of course, you can wrap this union with another structure/class, to same effect:
class MyClass
{
public:
union
{
struct
{
float x;
float y;
float z;
};
float xyz[3];
};
};
Also, why create your structure on heap (using "new")? Won't allocating on stack do?
EDIT: Oh, I get it. Well, it's definitely doable, but it is worth it only if you want as much compability with GLSL as possible. The idea is to create a "proxy" that stores references for each component variation. The tradeof is that vec2, instead of taking 8 bytes of memory will take 40 bytes. It will obviously get much, much worse for vec3 & vec4
class vec2
{
// private proxy, auto-convertible into vec2
struct proxy2
{
// store references, not values!
proxy2(float &x, float &y) : x(x), y(y) {}
// implicit conversion to vec2
operator vec2() { return vec2(x, y); }
// support assignments from vec2
proxy2& operator=(const vec2& vec)
{
x = vec.x;
y = vec.y;
return *this;
}
private:
// hide copy and assignment operators
proxy2(const proxy2&);
proxy2& operator=(const proxy2&);
// hide member variables
float& x;
float& y;
};
public:
vec2(float _x, float _y)
: x(_x), y(_y)
, xx(x, x), xy(x, y), yx(y, x), yy(y, y)
{}
vec2(const vec2& vec)
: x(vec.x), y(vec.y)
, xx(x, x), xy(x, y), yx(y, x) , yy(y, y)
{}
float x;
float y;
proxy2 xx;
proxy2 xy;
proxy2 yx;
proxy2 yy;
};
With this class you can get syntax pretty close to what GLSL offers:
vec2 v(1.0f, 2.0f);
vec2 vxx = v.xx; // 1, 1
vec2 vyx = v.yx; // 2, 1
vec2 vxy = v.xy; // 1, 2
vec2 vyy = v.yy; // 2, 2
v.yx = vec2(3, 4); // 4, 3
v.y = 5; // 4, 5
vec2::proxy2 proxy = v.xx; // compile error
v.xx = vec2::proxy2(v.x, v.y); // compile error
To extend this to support vec3 and vec4 simply derive from vec2 and vec3 respectively, create proxy3 and proxy4 structs and declare member for each component variation (27 for vec3 and mere 64 for vec4).
EDIT2: New version, that does not take extra space at all. Again, unions to the rescue! Converting proxy2 to a template and adding data member that matches vec2 components you can safely put it into an union.
class vec2
{
// private proxy, auto-convertible into vec2
template <int x, int y>
struct proxy2
{
// implicit conversion to vec2
operator vec2()
{
return vec2(arr[x], arr[y]);
}
// support assignments from vec2
proxy2& operator=(const vec2& vec)
{
arr[x] = vec.x;
arr[y] = vec.y;
return *this;
}
private:
float arr[2];
};
public:
vec2(float _x, float _y)
: x(_x), y(_y)
{}
vec2(const vec2& vec)
: x(vec.x), y(vec.y)
{}
union
{
struct
{
float x;
float y;
};
proxy2<0, 0> xx;
proxy2<0, 1> xy;
proxy2<1, 0> yx;
proxy2<1, 1> yy;
};
};
Hope this is what you are after.
EDIT3: I took me a while, but I came up with a working GLSL emulation library (includes swizzling) allowing you to run fragment shaders without modifications. If you are still interested, you should take a look.
C++ can accommodate syntax like vec.xyx, but it's not easy to write. And you won't get there by adding features one by one. It's better to list the requirements, select the tools, and make a straight shot.
What you need:
A storage class like std::array
Members named x, y, … xy, xz, … xyz, xzx, …
Something that converts those members to the desired output
Types to give the output the desired semantics
The first requirement is simple: use std::array.
Next you have to define 3 + 3^2 + 3^3 = 39 members. This can be done by copy-paste but you're better off with template metaprogramming. With a z member it's a must.
The types of the members are meaningless, but must tell the compiler how to choose the named elements from the array.
Example:
selection_vector< 0, 1, 0 > xyx;
selection_vector< 0, 1, 1 > xyy; // ad nauseam
Ideally these members would know how to select the elements with no state, but they will need to be initialized with this and take up one pointer each. So be aware that each 3-vector object wastes 312 bytes.
To make the members do something, you have to define conversion functions. So you have something like
selection_vector::operator array3_type() { return { ptr[0], ptr[1], ptr[2] }; }
Implicit conversion functions apply when performing assignment and passing as a function argument besides this, but not in many other situations. So to obtain vec.xyx.x or vec.xyx[ 1 ] the selection_vector type would need to define additional members.
Once you've defined the web of crazy types and operator overloads, you'll be able to save a few keystrokes…
Minor compromise
It sounds like you don't really want to compromise, but the ->* operator is worth mentioning. It's the best non-member operator overload for implementing subscripts.
This allows a pattern like
xyx_type xyx;
template< typename vec >
my_3vector< vec > operator->* ( vec &&v, xyx_type )
{ return { v[0], v[1], v[2] }; }
std::array< float, 3 > a { 0.5, 1.5, 9 };
my_3vector< … > b = a->*xyx;
You could even make my_3vector simply std::array and avoid any template metaprogramming. Make xyx_type an enumeration to avoid preprocessor metaprogramming too.
The ->* operator stands in for .. This makes things a lot easier, but note that ->* has funny precedence; it's lower than . and -> whereas you would expect it to be a peer.
Here is another solution possible, a slight variation to union-based example posted by #gwiazdorrr. It assumes
#include <cassert>
#include <algorithm>
#include <stdexcept>
struct MyClass
{
enum { size = 3 };
typedef float& reference;
reference x;
reference y;
reference z;
MyClass()
: x(xyz[0] = 0), y(xyz[1] = 0), z(xyz[2] = 0)
{}
MyClass(float x, float y, float z)
: x(xyz[0] = x), y(xyz[1] = y), z(xyz[2] = z)
{}
MyClass& operator=(MyClass const& other)
{
std::copy(other.xyz, other.xyz + size, xyz);
return *this;
}
// convenient indexed access
reference operator[](std::size_t index)
{
if (index < size)
return xyz[index];
else
throw std::out_of_range("index not less than size");
}
// raw data access
float* data() { return xyz; }
private:
float xyz[size];
};
int main()
{
MyClass c1;
MyClass c2(1, 2, 3);
c1 = c2;
assert(c1.data()[0] == c2[0]);
assert(c1.data()[1] == c2[1]);
assert(c1.data()[2] == c2[2]);
MyClass c3(c2);
assert(c2[0] == c3.x);
assert(c2[1] == c3.y);
assert(c2[2] == c3.z);
}
I assumed no access to C++11, thus the initialisation gymnastics in the constructors.