Title may be a little bit confusing but basically I have a class 'Quaternion' which has 2 parameters, the first being another instance of a class Vector3 and the other being a float.
Vector3 takes 3 floats as parameters and assigns them to x, y, and z.
I want to set default parameters for the Quaternion class but I am unsure how to set default parameters with a class as a parameter.
Vector3
class Vector3 {
public:
float x, y, z;
Vector3(float uX, float uY, float uZ) {
this->x = uX;
this->y = uY;
this->z = uZ;
}
};
Quaternion
class Quaternion {
public:
Vector3 axis;
float scalar;
Quaternion(Vector3 uAxis, float uScalar = 0) {
axis = uAxis;
scalar = uScalar;
};
};
I would like to have the default parameter for uAxis to be a Vector3 with x, y, and z set to 1, 0, 0 respectively, but i am unsure how i can do this.
I think this is what you were looking for:
class Quaternion {
public:
Vector3 axis;
float scalar;
Quaternion(Vector3 uAxis = Vector3(1.0, 0.0, 0.0), float uScalar = 0) {
axis = uAxis;
scalar = uScalar;
};
};
It is possible to call a constructor of a class to set a default parameter. Here is the corresponding cpp reference default arguments.
This is what you want. Always use the initialisation list on the constructor unless you have to do something with the parameters docs. Also I am passing the uAxis as const reference which is always a good thing to do for ADT (Abstract Data Types) Unless you have special requirements.
class Quaternion
{
Vector3 axis;
float scalar;
public:
Quaternion(const Vector3 & uAxis = Vector3(1.0, 0.0, 0.0), float uScalar = 0) :
axis(uAxis),
scalar(uScalar)
{
}
};
Another option would be to use default member initialization for axis within Quaternion. That way, just creating a Quaternion q{} would set axis to whatever you want. [Demo]
class Quaternion {
public:
Vector3 axis{1.0, 0.0, 0.0};
float scalar{};
Quaternion() = default;
...
};
For the Quaternion(Vector3 uAxis, float uScalar) constructor, it would be preferable to use a member initializer list:
Quaternion(Vector3 uAxis, float uScalar) : axis{uAxis}, scalar{uScalar} {};
Also, you can remove Vector3's constructor, making Vector3 an aggregate:
struct Vector3 {
float x{};
float y{};
float z{};
};
Vector3 v{1.1, 2.2, 3.3};
Related
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 8 months ago.
I have two classes that I want to define, Position and TangentVector, partially given as follows:
class Position
{
public:
Position(double x, double y, double z);
// getters
double x(){ return m_x };
double y(){ return m_x };
double z(){ return m_x };
void translate(const TangentVector& tangent_vector);
private:
double m_x;
double m_y;
double m_z;
}
class TangentVector
{
public:
Tangent(double x, double y, double z, Position position);
// getters
double x(){ return m_x };
double y(){ return m_x };
double z(){ return m_x };
private:
double m_x;
double m_y;
double m_z;
Position m_position;
}
The key thing to note with the classes is that TangentVector has a member of type Position (TangentVector depends on Position) while Position has a method that takes in an argument of type const TangentVector& (Position depends on TangentVector?).
For context's sake, Position is intended to represent a point on the unit sphere, and TangentVector describes a vector tangent to the sphere, with the origin of the vector specified by a Position. Since the definition of a VectorTangent requires a Position to be specified, it seems reasonable to say that VectorTangent depends on Position. However, now I want to define a function that takes a Position on the sphere, and "translates" it along the sphere by a direction and distance given by TangentVector. I would really like this translate method to live in the Position class, since it a function that modifies the state of Position. This would lend itself to the following usage, which I feel is fairly natural:
Position position{ 1.0, 0.0, 0.0 };
TangentVector tangent_vector{ 0.0, PI/2, 0.0, position };
position.translate(tangent_vector); // Now { 0.0, 1.0, 0.0 };
However, I fear that this results in some circular dependency. So...
Is this case an example of circular dependency? Is this case bad practice?
If so, how can this circular dependency be avoided? How can this code be modified such that it is in-line with good OOP practices?
(I considered making the Position m_position member a raw pointer instead. In this case, however, I intend m_position to be fully owned by TangentVector, rather than allow the possibility of it being altered external to the class. In the example usage code, I do not want the translate method to modify tangent_vector, which would happen if tangent_vector's constructor took in position as a pointer and stored it as a member.)
class Position takes only a reference to class TangentVector. Therefore you might pre-declare TangentVector as class TangentVector; before the declaration of class Position:
class TangentVector;
class Position
{
public:
Position(double x, double y, double z);
// getters
double x(){ return m_x };
double y(){ return m_x };
double z(){ return m_x };
void translate(const TangentVector& tangent_vector);
private:
double m_x;
double m_y;
double m_z;
};
I am having trouble initializing the class, I want to extend it a bit. This is the baseclass:
basefile.cpp
Class Point3d
{
public:
Point3d ();
Point3d (double x, double y, double z);
Point3d& set (double x, double y, double z);
double x, y, z;
}
Point3d :: Point3d (): x (0.0), y (0.0), z (0.0)
{
}
inline Point3d &
Point3d :: set (double xx, double yy, double zz)
{
x = xx;
y = yy;
z = zz;
return * this;
}
.....
Edit
I want when declaring Point3D pt {1,1}, it means z = 0, so if I didn't edit the original file, how to add a default initialization function z = 0 on base class but from another file, it looks like this:
Point3d::Point3d(double xx, double yy, double zz=0) { x = xx; y = yy; z = zz; }
//or
Point3d :: Point3d (double xx, double yy)
{
x = xx;
y = yy;
z = 0;
return * this;
}
I thought of using a derived class, but what I wanted was to extend the base class because I wanted to use the base class directly, I searched the partial class as well as many different ways but still failed.
You can't.
You must declare your member function, member method or constructor inside your class header to define it in another place.
You can only add members to a class in its definition and there can be only one definition of a class.
Extending classes at a later point is done via inheritance as you note in your question.
If you want to have a function set in your class, you need to declare it in the class definition:
class Point3d
{
public:
Point3d ();
Point3d (double x, double y, double z);
Point3d& set (double xx, double yy, double zz = 0);
double x, y, z;
};
Also note that you don't need the second definition of set, since you are already using a default argument for z.
You also have a few syntax errors in your code. In particular set lacks return values in its function head.
I've nested a class for use within another class and need to try accessing individual parts of it but can't. How would I go about doing this?
class Point
{
public:
Point() { float x = 0, y = 0; }
void Input(int &count); //input values
Rectangle myRec;
private:
float x, y;
};
class Rectangle
{
public:
Rectangle(); //side1 - horizontal, side2 - vertical
void SetPoint(const Point point1, const Point point2, const Point point3, const Point point4) { LLPoint = point1; LRPoint = point2; URPoint = point3; ULPoint = point4; }
float CalcSides(Point LL, Point LR, Point UL, Point UR);
private:
Point LLPoint, LRPoint, ULPoint, URPoint;
float side1, side2, length, width, area, perimeter; //side1 - horizontal, side2 - vertical
};
float Rectangle::CalcSides(Point LL, Point LR, Point UL, Point UR)
{
side1 = (LR.x - LL.x);
}
How can I access the x and y values for the points I've created in the Rectangle class?
If you really want to do this, then you can make the classes friends.
class Rectangle;
class Point
{
friend class Rectangle;
public:
Point() { x = 0; y = 0; }
void Input(int &count); //input values
private:
float x, y;
};
More likely though, you simply want to add accessors to the Point class as it is fairly useless as is.
class Point
{
public:
Point() { x = 0; y = 0; }
void Input(int &count); //input values
float getX() const { return x; }
float getY() const { return y; }
private:
float x, y;
};
Or, if Point is really going to be so simple and not need to maintain any invariants at all, just expose x and y as public members.
Also, you probably don't want to have Point contain a Rectangle but rather refer to one either through a pointer or a reference, if it refers to one at all. After all, a Point can be useful without reference to a Rectangle (e.g. - maybe it's used for Triangles too).
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();