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;
}
Related
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) {}
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);
Before anyone says anything I know this is probably not recommended but I am still curious if there is a better way to do it or reasons not to beyond just it's a strange thing to do.
I started looking into this because I wanted to access elements of an array directly with semantically named members in the class while still being able to iterate over the array and not have to call/create some getter or setter methods.
I have a class definition that looks something like this.
class Vertex{
public:
Vertex(float x,float y,float z,float w);
float v[4];
float &x,&y,&Z,&w;
};
And a constructor that looks like this. My question is. Is there a better way of doing what I am doing in the constructor?
Vertex::Vertex(float vx,float vy,float vz,float vw):
x(*const_cast<float*>( &this->v[0] )),
y(*const_cast<float*>( &this->v[1] )),
z(*const_cast<float*>( &this->v[2] )),
w(*const_cast<float*>( &this->v[3] ))
{
v[0]=vx;
v[1]=vy;
v[2]=vz;
v[3]=vw;
}
EDIT
I'm an idiot... you can just do it like Jonathan Wakely said.
x(v[0])
I guess I had some other problems before when I tried it. Oh well.
Vertex::Vertex(float vx,float vy,float vz,float vw):
v { vx, vy, vz, vw },
x(v[0]),
y(v[1]),
z(v[2]),
w(v[3])
{
}
I'd avoid writing reference members here. The reason is that reference members prevent defaulted (compiler generated) copy/assignment special members.
class Vertex{
public:
Vertex(float x,float y,float z,float w)
: v { x, y, z, w } { }
float &x() { return v[0]; }
float &y() { return v[1]; }
float &z() { return v[2]; }
float &w() { return v[3]; }
float const &x() const { return v[0]; }
float const &y() const { return v[1]; }
float const &z() const { return v[2]; }
float const &w() const { return v[3]; }
private:
float v[4];
};
You could go this way too:
class Vertex
{
public:
float x;
float y;
float z;
float w;
Vertex(float x, float y, float z, float w);
float&
operator[](int i)
{ return *(&x + i); }
float
operator[](int i) const
{ return *(&x + i); }
};
Probably, this variant is better (compared to other alternatives) because it requires less code and gives you the additional ability to iterate over Vertex in array-style.
Personally I like #sehe's answer best but I'll give you an alternative.
struct Vector4 {
float x;
float y;
float z;
float w;
};
union VectorUnion {
Vector4 vector;
float array[4];
};
Then you can just use the VectorUnion inside your Vertex class or on its own...
I am concerned about the fact that this is a C construct and that C++ struct is slightly different (it includes the vtable etc) but I think that it should work.
Again, I think #sehe's answer is better.
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.
Hi
I'm not a "native" C/C++ programmer. I'm able to write some basic things and do a coding that is common to other languages. But I have this problem and I don't know even how to ask different then explaining it (thus google searching won't fit me).
I've got in my code
typedef float point3[3];
And now I'm initilizing a bunch of points in 3D (x,y,z) by this:
point3 cpoint = {computeX(u,v),computeY(u,v)-5,computeZ(u,v)};
What functions does and values of u and v are irrevelent to my question (but I can provide code if asked).
Now I want to declare an array (one dimensional) of point3. So when I call array[0] I will get a point3 type variable. How I can do that?
EDIT:
I provided insufficient information. My bad. I need to retain: typedef float point3[3]; because I'm using OpenGL with GLUT and using this function glVertex3fv(cpoint); where cpoint is point3 type. So I'm pretty sure I can't use struct.
point3 cpoint[2] = {
{computeX(a, b), computeY(a,b)-5, computeZ(a,b)},
{computeX(c, d), computeY(c,d)-5, computeZ(c,d)}
}
Assuming C++, the simplest way would be to create a class to encapsulate your point structure and then create a vector of that type:
struct Point
{
Point(float x, float y, float z) : x_(x), y_(y), z_(z)
float x_;
float y_;
float z_;
};
typedef std::vector<Point> Points;
Then you can create a collection for storing the points:
Points points;
then later in the code, once populated you can access using:
Point a = points[ 3 ]; // for example
At first declare you own point3 like this
struct point3
{
float x;
float y;
float z;
};
then declare your array
point3 points[2] = {{calculateX(a1, b1), calculateY(a1, b1), calculateZ(a1, b1)},{calculateX(a2, b2), calculateY(a2, b2), calculateZ(a2, b2)}};
I'd like to expand Robin Welch's answer in a way which allows to stay compatible with the point3 typedef:
typedef float point3[3];
struct Point
{
Point(float x, float y, float z)
: x_(values_[0]), y_(values_[1]), z_(values_[2])
{
values_[0] = x;
values_[1] = y;
values_[2] = z;
}
float& x_;
float& y_;
float& z_;
point3 values_;
operator const point3&() const { return values_; }
operator point3&() { return values_; }
};
Now you can just use this simple struct, and pass it to OpenGL functions just as if it weren't this struct at all. It contains the original point3 array for OpenGL, yet convenient access and a constructor for yourself.
In C, I wouldn't initialize the array when declaring it unless it's a small array with constant values.
typedef float point3[3]; /* point is a type */
point3 *pp; /* pp points to objects of type point3 */
point3 ap[NELEMS]; /* each (of NELEMS) element of ap is of type point3 */
pp = malloc(NELEMS * sizeof *pp);
if (pp) {
/* use pp */
pp[0][0] = computeX(); pp[0][1] = computeY(); pp[0][2] = computeZ();
(*(pp+42))[0] = computeX(); (*(pp+42))[1] = computeY(); (*(pp+42))[2] = computeZ();
free(pp);
}
ap[0][0] = computeX(); ap[0][1] = computeY(); ap[0][2] = computeZ();