Const reference to a class member instead of a getter - c++

Classic way to get a reference to class member or its value we use getters like getValue(). Could this be an alternative way? :
class A{
ComplexClass value_;
public:
//No need. ComplexClass const& getValue() const { return value_; }
ComplexClass const& value = value_; /// ???
}
Will this work? How do you like such syntax?
UPD.
This point is to make user code simpler. Personally I better like auto x = a.value than auto x = a.getValue(). Of course this is a deal of taste.
Will this still work nice if:
class A{
public:
ComplexClass const& value = value_;
protected:
ComplexClass value_;
}
I ask because I met some troubles with one compiler.

One of the main reasons to prefer member functions over data members is flexibility and maintainability. If you only ever wrote some code once, perfectly, and it would never be changed or reused, then you could certainly have public data members that users refer to directly.
The interesting question is what happens when your code doesn't meet these criteria, e.g. if it is going to evolve, and if other people start using it. Then once you have a public data member, you are forced to always have that data member. Details of your class layout are now part of your public contract. Simple refactorings like moving common parts into nested member objects are no longer private and break existing users.
Your proposed reference data member adds almost no benefit over a public data member (except for in very trivial cases), and unlike member functions, non-static data members affect the class layout. Class layout is another thing you will probably want to keep stable once you have users, so that old, compiled libraries can continue to be linked against new user code. Member functions are much easier to evolve while keeping the data layout unchanged.
There's a nice example in the standard library where such a mistake was made: std::pair<T1, T2> is specified to contain public data members first and second. That means that all user specializations must adhere to the same specification, and cannot easily employ things like base layout optimizations. Had first and second been specified as member functions, such optimizations could be applied trivially.

Related

How to detect if a class has member variables?

Problem
I would like to detect if a class has member variables and fail a static assert if they do. Something like:
struct b {
int a;
}
static_assert(!has_member_variables<b>, "Class should not contain members"). // Error.
struct c {
virtual void a() {}
void other() {}
}
static_assert(!has_member_variables<c>, "Class should not contain members"). // Fine.
struct d : c {
}
static_assert(!has_member_variables<d>, "Class should not contain members"). // Fine.
struct e : b {
}
static_assert(!has_member_variables<e>, "Class should not contain members"). // Error.
struct f : c {
char z;
}
static_assert(!has_member_variables<f>, "Class should not contain members"). // Error.
Is there a way to achieve this with SFINAE template? This class may have inheritance or even multiple inheritance with virtual functions (no members in the base classes though).
Motivation
I have a pretty simple setup as follows:
class iFuncRtn {
virtual Status runFunc(Data &data) = 0;
};
template <TRoutine, TSpecialDataType>
class FuncRoutineDataHelper : public iFuncRtn {
Status runFunc(Data &data) {
static_assert(!has_member_variables<TRoutine>, "Routines shouldnt have data members!");
// Prepare special data for routine
TSpecialDataType sData(data);
runFuncImpl(sData);
}
class SpecificRtn :
public FuncRoutineDataHelper<SpecificRtn, MySpecialData> {
virtual Status runFuncImpl(MySpecialData &sData) {
// Calculate based on input
sData.setValue(someCalculation);
}
};
The FunctionalityRoutines are managed and run on a per tick basis. They are customized and can perform a wide variety of tasks such as contacting other devices etc. The data that is passed in can be manipulated by the routine and is guaranteed to be passed in on each tick execution until the functionality is finished. The right type of data is passed in based on the DataHelper class. I wan't to discourage future people from mistakenly adding data to the functionality routines as it is very unlikely to do what they expect. To force this, I was hoping to find a way with static assert.
You can solve this by depending on the compiler doing empty base class optimizations, by checking if a class derived from your T has the same size as an empty class with virtual functions:
template<typename T, typename... BaseClasses>
class IsEmpty
{
// sanity check; see the updated demo below
static_assert(IsDerivedFrom<T, BaseClasses...>::value);
struct NonDerived : BaseClasses... { virtual ~NonDerived() = default; };
struct Derived : T { virtual ~Derived() = default; };
public:
inline static constexpr bool value = (sizeof(NonDerived) == sizeof(Derived));
};
This should work with both single and multiple inheritance. However, when using multiple inheritance, it's necessary to list all base classes, like that:
static_assert(IsEmpty<Derived, Base1, Base2, Base3>::value);
Obviously, this solution rules out final classes.
Here's the updated demo.
Here's the original demo. (doesn't work with multiple inheritance)
You will have to mark the classes in some way or another. Pick a way you are comfortable with, a property or some kind of type integer member with an enum. Whoever makes sub-classes will have to follow your convention to make it work.
All other answers here will be some variant of this.
Any answer that uses a sizeof could not guarantee this will work between platforms, compilers, or even classes on the same platform and compiler, due to easily being able to fit a new member inside the default class member alignment, where the sizes of sizeof could easily end up the same for a sub-class.
Background:
As stated in your code and question, all of that is just plain and basic C ad C++ code, and is resolved entirely at compile time. The compiler will tell you if a member exists or not. After its compiled it's a mash of efficient, nameless, machine code with no hints or help for that kind of thing by itself.
Any name you use for a function or data member effectively disappears, as you know it and see it there, after compile and there is no way to lookup any member by name. Each data member is known only by its numerical offset from the top of the class or struct.
Systems like .Net, Java, and others are designed for reflection, which is the ability to remember class members by name, where you can find them at runtime when you program is running.
Templates in C++, unless mixed mode C++ on something like .Net, are also all resolved at compile time, and the names will also all be gone, so the templates by themselves buy you nothing.
Languages like Objective-C also are written to not fail necessarily if certain types of special members are missing, similar to what you are asking, but under the covers its using a lot of supporting code and runtime management to keep track independently, where the actual function itself and its code are still unware and rely on other code to tell them if a member exists or to not fail on null member.
In pure C or C++ you will need to just make your own system, and be literal about tracking dynamically what does what. You could make enums, or lists or dictionaries of name strings. This is what is normally done, you just have to leave hints for yourself. A class cannot be compiled in a way that gives implicit visibility to future sub-classes by definition, without using some form if RTTI.
Its common to put a type member on a class for this very reason, which could be a simple enum. I would not count on sizes or anything that might be platform dependent.

Restrict access to class

I've got some class - lets call it MyMutableClass, which implements MutableInterface.
class MutableInterface {
public:
void setMyPreciousData(int value);
int getMyPreciousData() const;
.... //and so on
};
However there is a huge part of code, which should not change the state this class instance, but it need to have a read access.
How to do it in the most polite manner? Should I create an additional ImmutableInterfaces, with getters only and inherits it by MutableInterface? Then I can choose, which one will be passed to another parts of code.
Second option would be to create another class, which object would encapsulate the MutableInterface implementation and provide an access only to a subset of its methods. Is that better?
Is there some well-known patter, which I'm not aware of?
This won't be what you want to hear, but I think it's important to be said in this case.
Inheritance describes a 'is kind of' interface. The derived thing 'is a kind of' the base thing.
A const thing is not 'a kind of' mutable thing. It's an immutable thing.
A mutable thing is not 'a kind of' immutable thing. It's a thing which happens to be mutable.
Mutability is a property of the thing, not a specialisation.
Therefore, inheritance is the wrong model and this is why in c++, constness is a property, not an interface.
If you really must hide the fact that sometimes a thing is mutable (one wonders why), then as mentioned in the comments, you probably want some kind of proxy view class, such as:
// this is the actual thing
struct the_thing
{
void change_me();
int see_me() const;
};
// and this is the proxy
struct read_only_thing_view
{
int see_me() const { return _reference.see_me(); }
the_thing& _referent;
};

Vectors Classes Private/Public

In C++ is always better to keep data of a class as private members.
If a class has a vector as member is better to put it as a private or public member?
If I have a vector as private member I cannot easily access to the member function of the vector. So I have to design the class with a method for every function I need to access the vector methods?
Example given:
class MyClass{
private:
std::vector<int> _myints;
public:
get_SizeMyints(){return _myints.size();}
add_IntToMyints(int x){_myints.push_back(x));
};
or is better to keep the vector public and call MyClass._myints.push_back(x)?
---------------------edit--------------
and just for clarity for what is needed this question:
snake.h:
enum directions{UP, DOWN, RIGHT, LEFT, IN, OUT, FW, RW };
class Snake
{
private:
enum directions head_dir;
int cubes_taken;
float score;
struct_color snake_color;
V4 head_pos;
public:
std::vector<Polygon4> p_list; //the public vector which should be private...
Snake();
V4 get_head_pos();
Polygon4 create_cube(V4 point);
void initialize_snake();
void move(directions);
void set_head_dir(directions dir);
directions get_head_dir();
void sum_cubes_taken(int x);
int get_cube_taken();
void sum_score(float x);
float get_score();
void set_snake_color();
};
so now I know how to change the code.
btw... a question, if I need to copy the vector in an other class like this: GlBox.p_list = Snake.p_list (works if are private) what will be an efficent method if they where private?
Running a for cycle to copy the the elements and pusshing back them in the GLBox.p_list seems a bit inefficent to me (but may be just an impression) :(
If it doesn't matter if someone comes along and empties the vector or rearranges all it's elements, then make it public. If it matters, then yes, you should make it protected/private, and make public wrappers like you have. [Edit] Since you say "it's a snake", that means it'd be bad if someone came and removed or replaced bits. Ergo, you should make it protected or private. [/Edit]
You can simplify a lot of them:
MyClass {
private:
std::vector<int> _myints;
public:
const std::vector<int>& get_ints() const {return _myints;}
add_IntToMyints(int x){_myints.push_back(x));
};
That get_ints() function will allow someone to look at the vector all they want, but won't let them change anything. However, better practice is to encapsulate the vector entirely. This will allow you to replace the vector with a deque or list or something else later on. You can get the size with std::distance(myobj.ints_begin(), myobj.ints_end());
MyClass {
private:
std::vector<int> _myints;
public:
typedef std::vector<int>::const_iterator const_iterator;
const_iterator ints_begin() const {return _myints.begin();}
const_iterator ints_end() const {return _myints.end();}
add_IntToMyints(int x){_myints.push_back(x));
};
For good encapsulation, you should keep your vector private.
Your question is not very concrete, so here's an answer in the same spirit:
Generally, your classes should be designed to express a particular concept and functionality. They should not just hand through another member class. If you find yourself replicating all the interface functions of a member object, something is wrong.
Maybe sometimes you really just need a collection of other things. In that case, consider a plain old aggregate, or even a tuple. But if you're designing a proper class, make the interface meaningful to the task at hand, and hide the implementation. So the main question here is, why do you need to expose the vector itself? What is its role in the class? What does its emptiness signify in terms of the semantics of your class?
Find the appropriate idioms and ideas to design a minimal, modular interface for your class, and the question might just go away by itself.
(One more idea: If for example you have some range-based needs, consider exposing a template member function accepting a pair of iterators. That way you leverage the power of generic algorithms without depending on the choice of container.)
Normally, good coding practice is to keep your data members private or protected, and provide whatever public methods will be needed to access them. Not all the methods of (in this case) vector, just what will be useful for your application.
That depends on your class's purpose. If you're trying simply trying to wrap the vector and want to use it as a vector you could make an argument for making the vector public.
Generally speaking I would suggest making it private and providing an appropriate interface to manipulate the container. Additionally this lets you change the container under the hood if a different container would ever be more appropriate (as long as you don't tie your public interface to the container type).
Further as an aside, avoid names that begin with underscores as there are some such identifiers reserved for the implementation and it's safer to just avoid all of them rather than trying to remember the rules in all cases.
A point to realize is that making the std::vector private is only half of the story when it comes to good encapsulation. For example, if you have:
class MyClass {
public:
// Constructors, other member functions, etc.
int getIntAt(int index) const;
private:
std::vector<int> myInts_;
};
...then arguably, this is no better than just making myInts_ public. Either way, clients will write code using MyClass which is dependent on the fact that the underlying representation requires the use of a std::vector. This means that in the future, if you decide that a more efficient implementation would utilize a std::list instead:
class MyClass {
public:
// Constructors, other member functions, etc.
int getIntAt(int index) const; // whoops!
private:
std::list<int> myInts_;
};
...now you have a problem. Since you can't access into a std::list by index, you would either have to get rid of getIntAt, or implement getIntAt using a loop. Neither option is good; in the first case, you now have clients with code that doesn't compile. In the second case, you now have clients with code that just silently became less efficient.
This is the danger of exposing any public member functions which are specific to your choice of implementation. It's important to keep flexibility/future maintenance in mind when designing your class interface. There are a number of ways you could do this with your particular example; see Mooing Duck's answer for one such interface that exposes iterators.
Or, if you would like to maximize code readability, you could design the interface around what MyClass logically represents; in your case, a snake:
class MyClass {
public:
// Constructors, etc.
void addToHead(int value);
void addToTail(int value);
void removeFromHead();
void removeFromTail();
private:
// implementation details which the client shouldn't care about
};
This offers an abstraction of a snake object in your program, and the simplified interface gives you the flexibility to choose whatever implementation suits it best. And if the situation arises, you can always change that implementation without breaking client code.
Theoretically in Object Oriented Programming any attributes should be private and gain access to them via public methods such as Get() and Set().
I think you question is not complete, but what I understand from what you're trying to achieve you need to inherit from std::vector and extend its functionality, to both satisfy your fast access needs and not messing around with encapsulation. (Consider reading on "Inheritance" first from any C++ book, or other OO language)
Having said that, your code might look as following:
class MyClass : public std::vector<int>
{
//whatever else you need goes here
}
int main(void)
{
MyClass var;
var.push_back(3);
int size = var.size(); // size will be 1
}
Hope this answered your question

What detectable differences are there between a class and its base-class?

Given the following template:
template <typename T>
class wrapper : public T {};
What visible differences in interface or behaviour are there between an object of type Foo and an object of type wrapper<Foo>?
I'm already aware of one:
wrapper<Foo> only has a nullary constructor, copy constructor and assignment operator (and it only has those if those operations are valid on Foo). This difference may be mitigated by having a set of templated constructors in wrapper<T> that pass values through to the T constructor.
But I'm not sure what other detectable differences there might be, or if there are ways of hiding them.
(Edit) Concrete Example
Some people seem to be asking for some context for this question, so here's a (somewhat simplified) explanation of my situation.
I frequently write code which has values which can be tuned to adjust the precise performance and operation of the system. I would like to have an easy (low code overhead) way of exposing such values through a config file or the user interface. I am currently writing a library to allow me to do this. The intended design allows usage something like this:
class ComplexDataProcessor {
hotvar<int> epochs;
hotvar<double> learning_rate;
public:
ComplexDataProcessor():
epochs("Epochs", 50),
learning_rate("LearningRate", 0.01)
{}
void process_some_data(const Data& data) {
int n = *epochs;
double alpha = *learning_rate;
for (int i = 0; i < n; ++i) {
// learn some things from the data, with learning rate alpha
}
}
};
void two_learners(const DataSource& source) {
hotobject<ComplexDataProcessor> a("FastLearner");
hotobject<ComplexDataProcessor> b("SlowLearner");
while (source.has_data()) {
a.process_some_data(source.row());
b.process_some_data(source.row());
source.next_row();
}
}
When run, this would set up or read the following configuration values:
FastLearner.Epochs
FastLearner.LearningRate
SlowLearner.Epochs
SlowLearner.LearningRate
This is made up code (as it happens my use case isn't even machine learning), but it shows a couple of important aspects of the design. Tweakable values are all named, and may be organised into a hierarchy. Values may be grouped by a couple of methods, but in the above example I just show one method: Wrapping an object in a hotobject<T> class. In practice, the hotobject<T> wrapper has a fairly simple job -- it has to push the object/group name onto a thread-local context stack, then allow the T object to be constructed (at which point the hotvar<T> values are constructed and check the context stack to see what group they should be in), then pop the context stack.
This is done as follows:
struct hotobject_stack_helper {
hotobject_stack_helper(const char* name) {
// push onto the thread-local context stack
}
};
template <typename T>
struct hotobject : private hotobject_stack_helper, public T {
hotobject(const char* name):
hotobject_stack_helper(name) {
// pop from the context stack
}
};
As far as I can tell, construction order in this scenario is quite well-defined:
hotobject_stack_helper is constructed (pushing the name onto the context stack)
T is constructed -- including constructing each of T's members (the hotvars)
The body of the hotobject<T> constructor is run, which pops the context stack.
So, I have working code to do this. There is however a question remaining, which is: What problems might I cause for myself further down the line by using this structure. That question largely reduces to the question that I'm actually asking: How will hotobject behave differently from T itself?
Strange question, since you should be asking questions about your specific usage ("what do I want to do, and how does this help me or hurt me"), but I guess in general:
wrapper<T> is not a T, so:
It can't be constructed like a T. (As you note.)
It can't be converted like a T.
It loses access to privates T has access to.
And I'm sure there are more, but the first two cover quite a bit.
Suppose you have:
class Base {};
class Derived : Base {};
Now you can say:
Base *basePtr = new Derived;
However, you cannot say:
wrapper<Base> *basePtr = new wrapper<Derived>();
That is, even though their type parameters may have an inheritance relationship, two types produced by specialising a template do not have any inheritance relationship.
A reference to an object is convertible (given access) to a reference to a base class subobject. There is syntactic sugar to invoke implicit conversions allowing you to treat the object as an instance of the base, but that's really what's going on. No more, no less.
So, the difference is not hard to detect at all. They are (almost) completely different things. The difference between an "is-a" relationship and a "has-a" relationship is specifying a member name.
As for hiding the base class, I think you inadvertently answered your own question. Use private inheritance by specifying private (or omitting public for a class), and those conversions won't happen outside the class itself, and no other class will be able to tell that a base even exists.
If your inherited class has its own member variables (or at least one), then
sizeof(InheritedClass) > sizeof(BaseClass)

a struct doesn't belong in an object oriented program

Or does it?
Should an object-oriented design use a language construct that exposes member data by default, if there is an equally useful construct that properly hides data members?
EDIT: One of the responders mentioned that if there's no invariant one can use a struct. That's an interesting observation: a struct is a data structure, i.e. it contains related data. If the data members in a struct are related isn't there's always an invariant?
In C++, structs and classes are identical except for the default public/privateness of their members. (This default is easily, and usually, overridden.)
However, most programmers think of a struct as a "data object" and a class as an "interactive object". That's not a bad thing; and in fact should be taken advantage of. If something is just an inanimate lump of data (even maybe if it has a couple of inspector methods), use a struct for it; it'll save a bit of effort when a programmer is trying to see what it's for.
Don't be a hiding zealot. If your get/set methods do nothing but simply copy verbatim the value onto/from a hidden, private field, you've gained nothing over a public member and only complicate unnecessarily your class (and, depending on the intelligence of the compiler, slow its usage a bit).
There's a case for not allowing direct access when your setter methods do some validation, copy the data somewhere else, process it a bit before storing it, etc. Same in the case of getters that actually calculate the value they return from multiple internal sources, and hide the way it's derived (I believe Bertrand Meyer speaks a bit about this in his book)
Or if allowing the users of your class to directly change such a value would have unintended side effects or breaks an assumption some of your member classes have about the values. On those situations, by all means, do hide your values.
For instance, for a simple "Point" class, that only holds a couple coordinates and colour, and methods to "Plot" it and "Hide" it on screen, I would see no point in not allowing the user to directly set the values for its fields.
In C# for example I use structs for some simple better-left-as-values data types:
public struct Point
{
int X;
int Y;
}
and for any P/Invoke to libraries where the arguments are structs you'll have to use them for certain.
Do they belong in the general design of an application? Of course they do, use a struct when it makes sense to do so. Just like you'd use a enum with bit flags when it makes sense to do so instead of resorting to some complicated string parsing for storing combined values.
In C++, the difference between a struct and a class is the default visibility of its contents (i.e. public for a struct, and private for a class). I guess this difference was to keep C compatibility.
But semantically, I guess this is subject to interpretation.
An example of struct
In a struct, everything is public (by default), meaning the user can modify each data value as desired, and still the struct remains a valid object. Example of struct:
struct CPoint
{
int x ;
int y ;
CPoint() : x(0), y(0) {}
int getDistanceFromOrigin() const
{
return std::sqrt(x * x + y * y) ;
}
} ;
inline CPoint operator + (const CPoint & lhs, const CPoint & rhs)
{
CPoint r(lhs) ;
r.x += rhs.x ;
r.y += rhs.y ;
return r ;
}
You can change the x value of a CPoint, and it still remains a valid CPoint.
Note that, unlike some believe, a C++ struct can (and should) have constructors, methods and non-member functions attached to its interface, as shown above.
An example of class
In a class, everything is private (by default), meaning the user can modify the data only through a well defined interface, because the class must keep its internals valid. Example of class:
class CString
{
public :
CString(const char * p) { /* etc. */ } ;
CString(const CString & p) { /* etc. */ } ;
const char * getString() const { return this->m_pString ; }
size_t getSize() const { return this->m_iSize ; }
void copy { /* code for string copy */ }
void concat { /* code for string concatenation */ }
private :
size_t m_iSize ;
char * m_pString ;
} ;
inline CString operator + (const CString & lhs, const CString & rhs)
{
CString r(lhs) ;
r.concat(rhs) ;
return r ;
}
You see that when you call concat, both the pointer could need reallocation (to increase its size), and the size of the string must be updated automatically. You can't let the user modify the string by hand, and forget updating the size.
So, the class must protect its internal, and be sure everything will be correctly updated when needed.
Conclusion
For me, the difference between a struct and a class is the dependencies between the aggregated data.
If each and every piece of data is independent from all the others, then perhaps you should consider a struct (i.e., a class with public data member).
If not, or if in doubt, use a class.
Now, of course, in C#, the struct and class are two different type of objects (i.e. value types for structs, and referenced types for classes). But this is out of this topic, I guess.
Technically, a struct is a class with the default visibility of public (a real class has a default visibility of private).
There is more of a distinction in common use.
A struct is normally just a collection of data, to be examined and processed by other code.
A class is normally more of a thing, maintaining some sort of control over its data, and with behavior specified by associated functions.
Typically, classes are more useful, but every so often there's uses for something like a C struct, and it's useful to have a notational difference to show it.
The matter is easy. If the class does have invariants to guarantee, you should never make the members constraining the invariant public.
If your struct is merely an aggregate of different objects, and doesn't have an invariant to hold, you are indeed free and encouraged to put its members public. That's the way std::pair<T, U> in C++ does it.
What's that invariant stuff?
Simple example: Consider you have a Point class whose x and y members must always be >= 0 . You can make an invariant stating
/* x >= 0 && y >= 0 for this classes' objects. */
If you now make those members public, clients could simply change x and y, and your invariant could break easily. If the members, however, are allowed to contain all possible values fitting their own invariants respectively, you could of course just make those members public: You wouldn't add any protection to them anyway.
A struct is essentially a model class but with different syntax.
public struct Point {
int x;
int y;
}
is logically the same as:
public class Point {
private int x;
private int y;
public void setX(int x) { this.x=x; }
public int getX(); { return x; }
public void setY(int y) { this.y=y; }
public int getY(); { return y; }
}
Both are a mutable model that holds pair of integer values called x and y. So I would say that it's a valid object oriented construct.
Yes. It's like a mini-class.
Yes, they do. They have different semantic than classes. A struct is generally considered and treated as a value type, while a class is generally considered and treated as a reference type. The difference is not as much pronunciated in every day programming; however, it is an imprtant difference when it comes to things like marshalling, COM interop and passing instances around.
I use structs regularly - mostly for data received from the network or hardware. They are usually wrapped in a class for use by higher level parts of the program.
My rule of thumb is a struct is always pure data, except for a constructor. Anything else is a class.
Most answers seem to be in favor of a struct as something to be acceptable and useful, as long as it does not have a behavior (i.e. methods). That seems fair enough.
However, you can never be sure that your object does not evolve into something that may need behavior, and hence some control over its data members. If you're lucky enough that you have control over all users of your struct, you can go over all uses of all data members. But what if you don't have access to all users?
A struct, as used in C or C++, and the struct used in C# ( or any .Net language ), are such different animals that they probably should not even have the same name... Just about any generalization about structs in one language can easily be false, or true for a completely unrelated reason, in the other.
If there is a need for invariant, make it a class. Otherwise, struct is OK.
See these similar questions:
When should you use a class vs a struct in C++?
What are the differences between struct and class in C++
plus:
According to Stroustrup in the C++ Programming Language:
Which style you use depends on circumstances and taste. I usually prefer to use struct for classes that have all data public. I think of such classes as "not quite proper types, just data structures."
Formally, in C++ a struct is a class with the visibility of its members set to public by default. By tradition structs are used to group collection of homogeneous data that have no particular reasons for being accessed by specific methods.
The public visibility of its members makes structs preferred to class to implement policy classes and metafunctions.
There's nothing wrong with using structs per se, but if you're finding yourself needing them, you should ask what's wrong with your analysis. Consider, eg, the Point class above: it gives some little improvement in readability, since you can always use
Point foo;
//...
foo.x = bar;
in place of, say, having a two element array as in
#define X 0
#define Y 1
//...
foo[X] = bar;
But classes are meant to hide details behind a contract. If your Point is in some normalized space, the values may range in the half-open interval [0.0..1.0); if it's a screen they may range in [0..1023]. If you use a struct in place of accessors, how will you keep someone from assigning foo.x = 1023 when x should be everywhere < 1.0?
The only reason C++ programmers used structs for Points is that back at the dawn of time --- 20 years ago, when C++ was new --- inlining wasn't handled very well, so that foo.setX(1023) actually took more instructions than foo.x = 1023. That's no longer true.
Structs are fine as long as they're kept small. As you probably know, they are allocated on the stack (not the heap) so you need to watch the size. They can come in handy for small data structures like Point, Size, etc. A class is usually the better choice though, being a reference type and all.