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) {}
Related
Is there an equivalent to Delphi's absolute in C++? I want to do the following:
// Structure A
struct A
{
double X;
double Y;
double Z;
}
// Structure B
struct B : A
{
double U absolute X;
double V absolute Y;
double W absolute Z;
}
I can use double & U = X in structure B but this will generate an additional pointer and change the size of the structure. Union is - I think - also not a solution, because structure B inherits structure A.
What I really want is to have access to the same memory by accessing for example X or U.
I like the idea of user2079303's answers, but want to inverse it.
Note - the question is named wrong and is violating "what is your real goal" or "show me your Z" rule. We do not need to mimic absolute keyword - it is total nonsense! we want to make pseudonyms for the record properties and use them interchangeably.
What I really want is to have access to the same memory by accessing for example X or U.
The quoted line is the ONLY line in the question that talks about the problem essence - making full pseudonyms.
So, let's start where user2079303 stopped and use the fact that C's unions do not have to be named, like it was used in https://stackoverflow.com/a/13624921/976391
So we just inverse the scopes.
/*union*/ struct coordinates {
/*struct*/ union {
double X;
double U;
};
/*struct*/ union {
double Y;
double V;
};
/*struct*/ union {
double Z;
double W;
};
};
Short version: There is no equivalent of the described language feature.
Long version C++:
There isn't an equivalent in C++. The member reference that you suggest gives you the same syntax, but indeed increases the size of the object.
Another close alternative is a member function, that returns a reference. That has no overhead (assuming inline expansion). A function call has different syntax than referencing a member though. But perhaps having identical syntax with member access is not important so this is what I suggest.
Long version C:
There is no inheritance in C at all, so there is nothing like the described "absolute" in it either.
we have several kinds of coordinates. Some of them are named x, y, z others (in another system) are named u, v, w.
Given this context, I would suggest a union (EDIT: It's better to swap the union and struct relation, see https://stackoverflow.com/a/41148089/2079303):
union coordinates {
struct {
float x, y, z;
} xyz;
struct {
float u, v, w;
} uvw;
};
If you want to interchangeably use XYZ and UVW, you can let each convert to the other.
// forward declare
struct B;
struct A
{
double X;
double Y;
double Z;
operator B() const;
}
struct B
{
double U;
double V;
double W;
operator A() const;
}
A::operator B() const { B b; b.U = X; b.V = Y; b.W = Z; return b; }
B::operator A() const { A a; a.X = U; a.Y = V; a.Z = W; return a; }
I have this class "Point" which takes in x and y as arguments.
However I need to create a constructor that initializes them to random values.
I don't know exactly how it is done. Here's my code:
I created constructors but I'm getting values that are absurd even when I set x and y.
#include <iostream>
#include <cmath>
#include <ctime>
using namespace std;
class Point
{
private:
double x;
double y;
public:
double get_x()
{
return x;
}
void set_x (double x)
{
this->x = x;
}
double get_y()
{
return y;
}
void set_y(double y)
{
this->y = y;
}
double distanceTo(Point p)
{
double x2 = p.get_x();
double y2 = p.get_y();
return sqrt( pow(x-x2,2) + pow(y-y2,2) );
}
Point(double x, double y)
{
x = rand()*1.0 / RAND_MAX * 100;
y = rand()*1.0 / RAND_MAX * 100;
}
Point(){};
};
void main()
{
Point a(1.2,0.5);
Point b;
b.set_x(1);
b.set_y(1);
cout << a.distanceTo(b);
system ("Pause");
}
That's because you aren't initializing your member variables, but changing a copy of the variables that are being passed into the constructor. Hence you're seeing garbage values as x and y (the class versions) are never initialized. You should change this to:
Point()
{
x = rand()*1.0 / RAND_MAX * 100;
y = rand()*1.0 / RAND_MAX * 100;
}
Further, you never call srand() anywhere - you need to do this at some point to properly seed the random generator.
Mistake: You changing local copies of variables passed to constructor by value (they have same name as member variables) and member variables left uninitialized so your program has undefined behavior.
How to fix: You must explicitly indicate what variable you are assigning to. Also, overload you constructor, so you will have one (default) for random values, and one for user-predefined.
Also:
it's better to pass values that not going to be changed in function as constant
you might want pass double by reference, not by value
use initializers lists instead of assignment in constructor body
when using constant references here you don't need to resolve names because you can't change constant values, so compiler will change member variables
Code:
class Point
{
public:
Point() :
x(rand()*1.0 / RAND_MAX * 100),
y(rand()*1.0 / RAND_MAX * 100)
{
}
Point(const double& x, const double& y) :
x(x),
y(x)
{
}
private:
double x, y;
};
int main()
{
Point pt(42, 3.14);
Point pt_random;
}
Same in accessor functions:
double GetX() const { return x; }
void SetX(const double& x) { Point::x = x; }
Because you're altering temporary variables in the constructor (name collision in the same scope). Try:
Point(double x, double y)
{
Point::x = rand()*1.0 / RAND_MAX * 100;
Point::y = rand()*1.0 / RAND_MAX * 100;
}
But that completely disregards arguments given to the constructor. But since now you know how to differentiate between different scopes of variables, you can go on from here, I believe.
Your default constructor does nothing. It doesn't even initialize the values which means they are going to have an unspecified value.
Your constructor taking two arguments just assigns to the arguments, because their names shadow the names of the members.
change
Point(){};
to
Point()
{
x = rand()*1.0 / RAND_MAX * 100;
y = rand()*1.0 / RAND_MAX * 100;
}
also I would advice to change your arguments\members name to avoid mistakes. I personally like to use m_ for members :
private:
double m_x;
double m_y;
You are getting a 'name collision'. In this function
Point(double x, double y)
{
x = rand()*1.0 / RAND_MAX * 100;
y = rand()*1.0 / RAND_MAX * 100;
}
The compiler is doesn't know which x you mean when you assign. The language rules will say that the input arguments should be assigned - but you should not rely on this - because it is needlessly confusing.
A good practice is to adopt a naming convention for member variables. Two common ones are to prefix members with "m" or "_". I like "m" personally.
Then your code becomes:
class Point
{
public:
double mX;
double mY;
Point(double x, double y)
{
mX = rand()*1.0 / RAND_MAX * 100;
mY = rand()*1.0 / RAND_MAX * 100;
}
}
Also the constructor arguments in this case are redundant, and can be removed.
Some of the other answers above are also correct - but it is a sign of bad class design if you have to explicity scope names ( e.g. Point:: ) in simple functions.
First, to get my concern across take a look at these two code segments I have prepared:
struct Quaternion
{
public:
float X, Y, Z, W;
Quaternion(float x, float y, float z, float w)
:
X(x), Y(y), Z(z), W(w)
{}
void Normalise()
{
float num = (((this->X * this->X) + (this->Y * this->Y)) +
(this->Z * this->Z)) + (this->W * this->W);
float num2 = 1.0f / (static_cast<float>(std::sqrt(static_cast<double>(num))));
this->X *= num2;
this->Y *= num2;
this->Z *= num2;
this->W *= num2;
}
void Conjugate()
{
this->X = -this->X;
this->Y = -this->Y;
this->Z = -this->Z;
}
};
The above being the 'local methods' within the class that I am referring to in the title..
Now lets take a look at what I mean by the 'static methods' inside the class.
struct Quaternion
{
public:
float X, Y, Z, W;
Quaternion(float x, float y, float z, float w)
:
X(x), Y(y), Z(z), W(w)
{}
static Quaternion& Normalise(Quaternion& quat)
{
float num = (((quat.X * quat.X) + (quat.Y * quat.Y)) +
(quat.Z * quat.Z)) + (quat.W * quat.W);
float num2 = 1.0f / (static_cast<float>(std::sqrt(static_cast<double>(num))));
// Assuming operator= overloaded..
quat = Quaternion(quat.X * num2, quat.Y * num2, quat.Z * num2, quat.W * num2);
return quat;
}
static Quaternion& Conjugate(Quaternion& quat)
{
// Assuming operator= overloaded..
quat = Quaternion(-quat.X, -quat.Y, -quat.Z, quat.W);
return quat;
}
};
My question is.. What is the tradeoff? The effect? To using these static class methods rather than local methods. Both have similar usage:
Edit: Ignore the *.ToString functionality, it is psuedocode - I'm sure you can imagine what it would do; therefore its implementation is redundant as it just prints out raw X, Y, Z, W values.
The 'local method' class usage:
int main()
{
Quaternion testQuat(6.0f, 6.0f, 6.0f, 1.3f);
std::cout << testQuat.ToString(); // (6, 6, 6, 1.3)
testQuat.Conjugate();
std::cout << testQuat.ToString(); // (-6, -6, -6, 1.3)
return 0;
}
Now the 'static method' class usage:
int main()
{
Quaternion testQuat(6.0f, 6.0f, 6.0f, 1.3f);
std::cout << testQuat.ToString(); // (6, 6, 6, 1.3)
testQuat = Quaternion::Conjugate(testQuat);
std::cout << testQuat.ToString(); // (-6, -6, -6, 1.3)
return 0;
}
So what is the difference? These are static methods not objects. Which is preferable? Is it just a matter of design choice?
They are two totally different things. One of them modifies the object in place a la OOP, the other returns a different object a la functional style. If it was my choice, I would keep both of them as there are use cases for both of them. And I would implement the functional styles as free functions based on the member functions, i.e.:
Quaternion normalize( Quaternion quat )
{
quat.normalize();
return quat;
}
[I'm explicitly taking quat by value here, gives a chance for copy-elision]
Note that your static implementations are wrong, they are returning a reference to a temporary. That's undefined behavior, you should get a warning from your compiler and if you are lucky enough a runtime crash as well.
First off, your second approach shouldn't compile although I think MSVC++ has an error allowing temporary objects to be bound to non-const references. Even adding const& doesn't make the functions better: They still don't work because the caller gets hold of a reference to a temporary. So much for the implementation.
With respect to interface design, I think the real trade-off isn't between static members (you can have them additionally, if you want to) but whether the functions taking no parameters should mutate the object themselves or should return a correspondingly modified object:
// return a copy:
Quaternion Quaternion::conjugate() const {
return Quaternion(-this->X, -this->Y, -this->Z, this->W);
}
// modify the object itself:
void Quaternion::conjugate() {
this->X = -this->X;
this->Y = -this->Y;
this->Z = -this->Z;
}
Although these two overload actually can live in the same class I would not provide both of them! It is a choice of interface which one is preferable. I would personally prefer the latter and probably create a static member mutating the object itself:
/* static */ void Quaternion::conjugate(Quaternion& object) {
object = object.conjugate();
}
Besides the other answers about differences between the two approaches, the static methods are difficult to mock/stub if you want to employ in unit tests.
For example, suppose that you have a class named ClassThatUsesQuaternion that uses Quaternion. If Quaternion have a lot of static methods you will always have real data. On the other hand, if you transform Quaternion methods into virtual methods, you will be able to redefining all methods, creating a environment test under your control. You can even add a mock framework like gmock to put your expectations.
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.
I have Struct like these
typedef struct sample
{
double x,
double y,
double z
}s1;
s1 s;
will the content in s variable initialized or not?
What will be the values of x,y,z?
thanks
x, y and z won't be initialized if s is defined in a function scope. They would be containing some unspecified values. At file scope the data members would be initialized to their default values.
In C++ however you can have a constructor initializer list to initialize the data members
For example
struct ABC
{
int x;
int y;
ABC(): x(1),y(2){}
};
ABC s; // x and y initialized to 1 and 2 respectively
In C++ you also have default initialization and value initialization to initialize data members.
In the code you presented, the fields will be uninitialized. You can add a constructor (if you need/can), or in case you need the POD-ness (some part of your code depends on some of those properties) and you cannot add a constructor, you can still value-initialize the struct (i.e. set each member to 0) at the place of use:
struct sample // typedef not required
{
double x,
double y,
double z
};
sample s = sample(); // will set all members to 0.0
Now, if you want to initialize different members with some particular values, because it is an aggregate you can use aggregate initialization:
sample s = { 1.0, 3.0 };
That will set x to 1.0, y to 3.0. Since there is no value for z, the compiler will set it to 0.0. Note that this means that sample s = {}; is equivalent to sample s = sample();
If it is C++, you could make constructor.
struct s1
{
s1( const double x = 0.0, const double y = 0.0, const double z = 0.0 )
: x(x), y(y), z(z)
{
};
double x;
double y;
double z;
};
s1 s;
Built-in types like double and int are initialised if the variable is static or at namespace/file scope, otherwise - for efficiency reasons - they're not initialised unless a constructor indicates that's useful.
Note: this answer addresses the "s1 s;" situation you describe. It is possible to provide an explicit initialisation when defining the variable, but that's another case.
To add a constructor so:
struct X
{
X() : x_(0), y_(0), z_(0) { }
double x, y, z;
};