C++: direct accessors or access functions within class? - c++

I have two versions of a class named 'vertex', one that uses direct accessors for the coordinates:
struct vertex
{
// Coordinates
std::array<double, 3> coords;
// Direct accessors
double & x;
double & y;
double & z;
// Constructor
template<typename... T> vertex(T &&... coordinates) :
coords{{ std::forward<T>(coordinates)... }},
x( coords[0] ), y( coords[1] ), z( coords[2] )
{ }
};
and other that uses access functions:
struct vertex
{
// Coordinates
std::array<double, 3> coords;
// Access functions
double & x() { return coords[0]; }
double & y() { return coords[1]; }
double & z() { return coords[2]; }
// Constructor
template<typename... T> vertex(T &&... coordinates) :
coords{{ std::forward<T>(coordinates)... }}
{ }
};
Which approach is better for this specific case? I would appreciate any other suggestions. Thanks!

I normally would go through functions, for encapsulation purposes.
But this is a quite particular case, because you are dealing with vertices. If you plan to manipulate a lot of those objects (rendering or trasforming meshes), then direct access has some benefits in term of performances.
Some graphic libraries use direct access (and some books suggests too) for vector-like operations in real-time environments where efficiency it's a must.
Have a look at Ogre::Vector3 for example.
Despite that I wouldn't do what you are doing in your first solution. Like other said
you are doubling the used space for no reason (for eventually a lot of vertices).
From my point of view, in a context of high performance this could be the best vertex:
class Vertex
{
public:
double X;
double Y;
double Z;
};

I think getters are better. First approach creates objects of bigger size for no real benefit.

I'd go with the function - it allows you to change your mind more easily in the future. Furthermore, you can't do this:
double & x() { return coords[0]; }
double & y() { return coords[1]; }
double & z() { return coords[2]; }
double x() const { return coords[0]; }
double y() const { return coords[1]; }
double z() const { return coords[2]; }
with the accessors.

Well, I'd say the first one is better for a few reasons:
You're unlikely to be performing additional processing mid-get or mid-set on a vertex coordinate.
Since operations on vertices are usually done very often in loops and vertices are often related to rendering, the first option (direct access) is likely to give you better performance.
Encapsulation isn't a must if you're going to be directly accessing members with trivial getters and setters. It's just Object Orientation by dogma.
That being said, the second approach has advantages too, such as an unchanging interface more resilient to change. I'd still stick with the first one.

If you really want direct write access to the members (which it appears you do and may be appropriate in this case), then I would suggest the inline functions. This gives you flexibility to profile and inject extra capability into the accesses in the future should you desire to do so.

I think the best solution would be to remove the reference of the second option and add setters. But if these are the only choices the second would be slightly better.

Related

C++ is there way to access a std::vector element by name?

I am experimenting with a simple vertex class.
class Vertex
{
public:
std::vector<float> coords;
//other functionality here - largely irrelevant
};
And lets say we create a Vertex object as below:
Vertex v0(1.f, 5.f, 7.f);
I am wondering if there is anyway to assign a name to each element of a vector?
Let's say that each std::vector will only ever have a size of 3. I know I can access an element or index of the vector in a way such as v0.coords[0] through to v0.coords[2];
However, I am wondering if there is a way in which I could assign a name to each element of the vector, ie:
v0.coords.x == v0.coords[0];
v0.coords.y == v0.coords[1];
v0.coords.z == v0.coords[2];
So that if I was to access the vector, I could access via a name rather than an index.
Is such a thing possible? If so, how do I go about creating such aliasing?
I am wondering if there is anyway to assign a name to each element of a vector?
No, there is not. At least, not the way you want.
I suppose you could use macros, eg:
#define coords_x coords[0]
#define coords_y coords[1]
#define coords_x coords[2]
Now you can use v0.coords_x, v0.coords_y, and v0.coords_z as needed.
Or, you can use getter methods, eg:
class Vertex
{
public:
vector<float> coords;
//other functionality here - largely irrelevant
float& x(){ return coords[0]; }
float& y(){ return coords[1]; }
float& z(){ return coords[2]; }
};
Now you can use v0.x(), v0.y(), and v0.z() as needed.
But really, in this situation, there is just good no reason to use a vector at all. It is simply the wrong tool for the job. Use a struct instead, eg:
struct Coords
{
float x;
float y;
float z;
};
class Vertex
{
public:
Coords coords;
//other functionality here - largely irrelevant
};
Alternatively:
class Vertex
{
public:
struct
{
float x;
float y;
float z;
} coords;
//other functionality here - largely irrelevant
};
Now you can use v0.coords.x, v0.coords.y, and v0.coords.z as needed.

Difference between the dot operator and a get method

I have a vector class
class Vector {
public:
double x, y, z;
Vector add(Vector v) {
return Vector(x+v.x, y+v.y, z+v.z);
}
};
and I have a class Ray
class Ray {
public:
Vector origin, direction;
Vector getOrigin() { return origin; }
};
In some method, I do:
Vector x = ray.origin().add(normal); // doesn't work
Vector y = ray.getRayOrigin().add(normal); // works
error message: Type vector doesn't provide a call operator
Why can't I just access the vector directly?
Because origin is not a function. Remove the parentheses when you access it.
Xīcò has the correct solution, but not the right symptom.
origin doesn't have to be a function. The Vector class could overload operator() and be called as if it were a function, and that's the message the compiler is trying to get across.
ray.origin allows anyone to do anything to ray's origin member including things that could be harmful to ray. Very uncool. The purpose of setters and getters is to regulate access to member variables. The goal is self defence.
OP's getOrigin method doesn't return origin. It returns a copy of origin. A malicious cretin can do anything they want to the copy without breaking ray. This is most often the right way unless the object returned is intended to be modified or prohibitively expensive to copy. In that modification case, lock down the returned object with private data, and getters and setters of it's own. In the expensive copy case, declare the return value to be const to reduce the possibility of damage.
A good setter will vet all input to the origin member before allowing the change to take place. If the caller tries to feed in values that are inconsistent with origin, ray can slap it down.
Directly accessing origin through . allows ray no defence whatsoever. It also prevents ray from changing the implementation of origin without also chancing origin's users.
Whether these are concerns with a pair of simple classes like Vector and Ray, is a matter of coding style and necessity, but locking down data access to the minimum necessary is generally a good habit to get into and a must when developing complicated software.
class Vector {
public:
double x, y, z;
Vector add(Vector v) {
return Vector(x+v.x, y+v.y, z+v.z);
}
};
class Ray {
public:
Vector origin, direction;
Vector getOrigin() { return origin; }
Vector& getOrigin2() { return origin; }
};
int main() {
Ray ray;
Vector v1 = ray.origin; // returns origin member
Vector v2 = ray.getOrigin(); // returns a copy of origin member
Vector v3 = ray.getOrigin2(); // same as v1, returns origin member
}

What is the difference between using the friend keyword, and using a member function to modify private variables inside of a class?

As the question asks...
What is the difference between:
class MyClass
{
public:
MyClass(){
m_a = 0;
}
private:
int m_a;
friend void set_a(MyClass &a);
};
void set_a(MyClass &a)
{
std::cout << a.m_a << std::endl;
a.m_a = 500;
std::cout << a.m_a << std::endl;
}
int main(void) {
MyClass my_class_instance;
set_a(my_class_instance);
system("pause");
}
and:
class MyClass
{
public:
MyClass(){
m_a = 0;
}
void set_a(){
std::cout << this->m_a << std::endl;
this->m_a = 500;
std::cout << this->m_a << std::endl;
}
private:
int m_a;
};
int main(void) {
MyClass my_class_instance;
my_class_instance.set_a();
system("pause");
}
Is it simply the preferred structure of the function, or are there real, measurable differences? From what I can tell, both functions achieve the same results in all circumstances, except if you had multiple overloads for the first example, that took different types of objects.
As the C++ FAQ says: Use a member when you can, and a friend when you have to.
There are situations where making friend a free function is preferable, most situations related to the fact that the first parameter of a member function is always of that class (Its the hidden *this parameter).
One example is arithmetic operators overloading:
Suppose you write a complex class which represents complex numbers. Using a member operator+() you could write expressions like complex + float, but not float + complex. But you could do it with the free form of the operator+:
class complex
{
...
friend complex operator+( float f , complex c );
};
This whole question comes down to "Why would I use friends in C++?". The answer is that when used properly, friends enhance encapsulation. This is an FAQ:
Do friends violate encapsulation?
Your example is too short and too abstract, of course. Some better, real life examples I could think of from the top of my head involve iterators. You may have many iterator objects referring to only one container object, and you may want the iterator to be able to access private member variables of the container. At the same time, you don't want the container to expose those variables to the rest of the world.
Such a design could be perfectly implemented with the friend feature.
Many people defend that making accessor methods, you can in a later stage of development put barriers to the incorrect access to the member variables (or even change the member variables totally) without breaking your (correct) clients.
One classical case is of a
class ComplexNumber {
double real, imaginary;
public:
double re() { return re; }
double setRe(double v) { return re = v; }
// and so on ...
};
one day you discover, in some maintenance, that you need the polar coordinates for that number, so you add the methods
double rho() { /* calculate rho */ }
double theta() { /* calculate theta */ }
double setRho(double v) { /* calculate real, imaginary, based on the new rho */ }
and so on.
Later yet, you discover that the users of the class use far more often polar than Cartesian coordinates for complex numbers, and that the conversions have been the bottleneck of a performance problem, so you ditch real and imaginary and store rho and theta, and change the getter and setter methods for the new -- more efficient -- storage for rho, theta, re, im, and so on. All the clients of your class will recompile without problems, because you changed your implementation but kept your interfaces stable.

VBO of std::vector<MyClass*> and correct strides

I'm wondering how to get the maximum data locality and performance for the following problem without data copy.
I've a std::vector< MyClass* > where MyClass is something like
class MyClass
{
public:
MyClass(int n,double px,double py,double pz)
{
someField=n;
x=px;
y=py;
z=pz;
anotherField=100;
anotherUnusefulField=-10.0;
}
int someField;
int anotherField;
double x;
double y;
double z;
double anotherUnusefulField;
};
std::vector<MyClass*> myClassVector;
// add some values and set x,y,z
for (std::vector<MyClass*>::iterator iter = myClassVector.begin(); iter!=myClassVector.end();++iter)
{
MyClass *tmp = *iter;
tmp->x+=1.0;
tmp->y+=2.0;
tmp->z+=3.0;
}
I'm iterating frequently on these data and I also would like to enforce data locality. The data contained in the pointer to MyClass should be sent to a OpenGL vertex array, where the vertices are ONLY determined by x,y,z variables. As you may imagine is difficult to correctly set the strides, so I'm here to ask if there are other (portable) solution to this problem.
(p.s. I've already read the post VBOs with std::vector but my case is basically different because I have pointers and I also have other variables inside the class.)
I have pointers
Those pointers are useless to OpenGL, as they're in client address space. Also OpenGL doesn't dereference second level pointers.
and I also have other variables inside the class.
Well, then don't do this. If you passed those class instances to OpenGL you'd copy a lot of useless data. I recommend you just store a index into a tightly packed std::vector or array in your class members, and a reference to the vector/array itself. You can use getter/setter/referencer member functions to abstract away the access to the vector, i.e.
class …
{
// …
std::vector<v_t> *v;
size_t index_v;
x_t getX() const { return (*v)[index_v]; }
x_t setX(x_t x) { return (*v)[index_v] = x;}
x_t &x() { return (*v)[index_v]; }
};

how to avoid this duplicate code using templates in C++

I would like to eliminate duplicity of code in this problem:
class PopulationMember
{
public:
vector<int> x_;
vector<int> y_;
}
class Population
{
vector<PopulationMember*> members_;
void doComputationforX_1(); // uses the attribute x_ of all members_
void doComputationforX_2();
void doComputationforX_3();
void doComputationforY_1(); // exactly same as doComputationforX_1, but
void doComputationforY_2(); // uses the attribute y_ of all members_
void doComputationforY_3();
EDIT: // there are also functions that use all the members_ simultaniously
double standardDeviationInX(); // computes the standard deviation of all the x_'s
double standardDeviationInY(); // computes the standard deviation of all the y_'s
}
The duplicity is causing me to have 6 methods instead of 3. The pairwise similarity is so
striking, that I can get the implementation of doComputationforY_1 out of doComputationforX_1 by simply replacing the "x_" by "y_".
I thought about remaking the problem in this way:
class PopulationMember
{
public:
vector<vector<int>> data_; // data[0] == x_ and data[1] == y_
}
But it becomes less clear this way.
I know that a precompiler macro is a bad solution in general, but I do not see any other. My subconciousness keeps suggesting templates, but I just do not see how can I use them.
If you want to keep x_ and y_ separately in the same class PopulationMember then it's better to choose pass by value solution rather than template solution:
Define the generic method as:
void doComputationfor (vector<int> (PopulationMember::*member_));
// pointer to data ^^^^^^^^^^^^^^^^^^^^^^^^^^
Call it as:
doComputationfor(&PopulationMember::x_);
doComputationfor(&PopulationMember::y_);
Remember that if your doComputationfor is large enough then, imposing template method would make code duplication.
With the pointer to member method, you will avoid the code duplication with a little runtime penalty.
If the API you have specified is exactly what you want users of the class to see, then just make private methods in Population called doComputation_1( const vector<int> &v ) { do stuff on v; }
And then make the public implementations 1 line long:
public:
void DoComputationX_1() { doComputation_1( x_ ); }
void DoComputationY_1() { doComputation_1( y_ ); }
private:
// drop the 'const' if you will need to modify the vector
void doComputation_1( const vector<int> &v ) { do stuff on v; }
I don't feel like this is the right solution, but I can't piece together what your class is really trying to do in order to offer up anything more meaningful.