I have two different structs which I want to convert to each other like this:
PointI a = PointI(3,5);
PointF b = a;
I assume that I will need to do something like the code below:
struct PointF
{
PointF operator=(PointI point){
x = point.x;
y = point.y;
return *this;
}
float x, y;
};
struct PointI
{
PointI operator=(PointF point)
{
x = point.x;
y = point.y;
return *this;
}
int x, y;
};
But the problem is that PointF uses PointI before it is declared. From what I've read in other questions, I understand that I can declare PointI before defining both structs, and then use a pointer. Though it seems that I won't be able to access the variables x and y from that pointer, as these are not defined yet.
Is there a way I can add these variables to the struct declaration before defining them? Or is there a better way to solve this problem?
First, forward declare one of the structs and fully declare the other. You'll need to use either a reference or pointer for the forward declared type, since the compiler doesn't have its definition yet:
struct PointI;
struct PointF
{
PointF operator=(const PointI& point);
float x, y;
};
Next, you need to fully declare the struct you forward declared:
struct PointI
{
PointI operator=(const PointF& point);
int x, y;
};
Now you can go ahead and define the operator= functions for each:
PointF PointF::operator=(const PointI& point)
{
x = point.x;
y = point.y;
return *this;
}
PointI PointI::operator=(const PointF& point)
{
x = point.x;
y = point.y;
return *this;
}
Note that you should change your operator= functions to return references rather than copies, but that's outside the scope of this question/answer.
Related
I have a class Particle:
class Particle {
private:
float x, y, z;
// ...
public:
// ...
float* getPos() {
float p[3] = {x, y, z};
return p;
}
// ...
};
I would call this method like:
Particle a = Particle();
// ...
float* pos = a.getPos();
And then reference the position elements with pos[0] through pos[2].
g++ spouts warning message as stated in the title. But the functionality is exactly how I want it: returning an array. Why does the warning exist and is there a "proper" way to do it?
You can't return a C-array like that, return std::array instead:
std::array<float, 3> getPos() {
std::array<float, 3> p = {x, y, z};
return p;
}
You'll need to include <array> for that.
Personally, I'd skip std::array/std::vector here, because in your particular case, the position of each value imposes independent meaning. In general, sequence types have ordering, tuples have structure; if the element count is fixed (and often heterogeneous) and sorting (or otherwise reordering the values) is intrinsically nonsensical (e.g. in the case of a coordinate, swapping the x and y values changes the meaning), then a tuple makes more sense.
In this case, you could just declare:
std::tuple<float, float, float> getPos() {
// C++17 or higher allows list initialization
return {x, y, z};
// Pre-C++17 you use the std::make_tuple helper
return std::make_tuple(x, y, z);
}
The advantage here is that you can then unpack the result in the caller easily, either with std::tie:
float x, y, z;
std::tie(x, y, z) = a.getPos();
or on C++17 or higher with structured bindings, it's even nicer, since you can declare and initialize the variables with auto, rather than declaring with explicit types, then reassigning with tie:
auto [x, y, z] = a.getPos();
You can store the tuple itself and use std::get if you prefer, but unpacking to useful names rather than obscure std::get indices usually makes for much cleaner code.
You're not returning an array. It's impossible to return an array in C++. You're returning a pointer to an array which no longer exists. Hence the warning.
You could make the array a part of your class and return a pointer to that. In general I wouldn't call that good design
class Particle {
private:
float pos[3];
// ...
public:
// ...
float* getPos() {
return pos;
}
// ...
};
You could return a vector<float> instead. You could return an array<float,3> instead. You could ask yourself why you need this.
p[3] will be destroyed when it goes out of scope so you shouldn't return a pointer to it.
Either return a std::array<float, 3> by value or consider making a class for positions too, and return a Position object, or a reference to it. Example:
struct Position {
float x, y, z;
};
class Particle {
private:
Position m_pos;
// ...
public:
// ...
Position const& getPos() const { return m_pos; }
// ...
};
I'd suggest that you're function is indicative of poor design. Provide getter methods an allow the user of your class to access member variables:
class Particle {
private:
float x, y, z;
public:
float GetX() const { return x; }
float GetY() const { return y; }
float GetZ() const { return z; }
};
Given const Particle a this will let you initialize an array as follows: const float pos[] = { a.GetX(), a.GetY(), a.GetZ() }
Creating a Particle method to allow the user to populate a float[] will encourage the user toward one of the following bad practices:
float* Particle::GetPos() const { return new[3]{ x, y, z }; } creates dynamic memory without clearly informing the caller that the memory needs to be released
array<float, 3U> Particle::GetPos() const { return { x, y, z }; } requires the allocation and creation of a temporary to populate a float[]
void Particle::GetPos(float* param) const { param[0] = x; param[1] = y; param[2] = z; } misses the opportunity for constant arrays and incurs potential caller misuse, as it's not clear that param must have room for at least 3 floats
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 a class, for example:
class Vector
{
float x, y, z
};
Vector v;
And a pointer:
float *c = &v.x;
Will it be works correctly, when I'll use increment operator for access to y and z members?
P.S. Bad style to do by this way, but it's sport interest.
Will it be works correctly, when I'll use increment operator for access to y and z members?
No. Undefined behavior. You can't perform pointer arithmetic across objects and you can't guarantee struct padding.
You can do stuff like this though:
class Vector
{
float v[3];
int& x() { return v[0]; }
int x() const { return v[0]; }
// and so on ...
};
I have a struct that represents a vertex. It has x, y and z fields as well as several others. Recently I came into conclusion that for certain functionality I will need to access the coordinates of the vertex as an array. I didn't want to "pollute" the code with temporary variables or change all places that look like this v.y to this v.coord[1] which is not nice nor elegant. So I thought about using a union. Something like this should work:
struct {
float x,y,z;
} Point;
struct {
union {
float coord[3];
Point p;
};
} Vertex;
This is good, but not perfect. The point class has no point being there. I want to be able to access y coordinate simply by typing v.y (and not v.p.y).
Can you suggest a hack to solve this (or tell me that it is not possible)?
A good C++ approach is to use named accessors that return references to the elements:
class Point {
public:
float& operator[](int x) { assert(x <= 2); return coords_[x]; }
float operator[](int x) const { assert(x <= 2); return coords_[x]; }
float& X() { return coords_[0]; }
float X() const { return coords_[0]; }
float& Y() { return coords_[1]; }
float Y() const { return coords_[1]; }
float& Z() { return coords_[2]; }
float Z() const { return coords_[2]; }
private:
float coords_[3];
};
With this approach, given a Point p;, you can use both p[0] and p.X() to access the initial element of the internal coords_ array.
OK, this should work for you
struct {
union {
float coord[3];
struct
{
float x,y,z;
};
};
} Vertex;
What this code does is that it unions the array with the structure, so they share the same memory. Since the structure doesn't contain a name, it is accessible without a name, just like the union itself.
Can I have a method which takes arguments that are denoted with the same names as the members of the holding class? I tried to use this:
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
x = x;
y = y;
};
};
... but it doesn't seem to work.
Is there any way of accessing the the instance the namespace of which I'm working in, similar to JavaScript's this or Python's self?
It's generally a good idea to avoid this kind of confusion by using a naming convention for member variables. For example, camelCaseWithUnderScore_ is quite common. That way you would end up with x_ = x;, which is still a bit funny to read out loud, but is fairly unambiguous on the screen.
If you absolutely need to have the variables and arguments called the same, then you can use the this pointer to be specific:
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
}
};
By the way, note the trailing semi-colon on the class definition -- that is needed to compile successfully.
Yes, you should be able to write this using the "this" keyword (which is a pointer in C++):
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
}
}
In C++ the current instance is referenced by the const pointer this.
class Foo {
public:
int x, y;
void set_values(int x, int y)
{
this->x = x;
this->y = y;
};
};