The immediate difference is that users of the class can assign to the values of w
and h
in the first example, but not the second.
The difference for future code changes is that the author of the class can change the way that foo
's data is stored in the second example, but not the first. For example if the class represents a rectangle, then you could switch to storing the co-ordinates of the corners, and calculate the width and height when requested.
There is no certain way that is "better". If you have a class that is defined to be a dumb data container, that users can read from and write to, and it is guaranteed that it will not in future perform any clever calculations, then you can use public data members. An example of this in the standard libraries is std::pair
, which has public data members first
and second
. Many OOP programmers will (on principle) never define or document any such guarantee, but the designers of the C++ standard libraries do not agree with this absolute principle. In any case C++ is not designed on strict OOP principles.
If you have a class that just so happens to store values that are useful to the user, but is not guaranteed to store them as members, then you would use accessors if necessary. An example in the standard libraries is std:vector
, which has functions begin()
and end()
. In some implementations of vector
they just return the values of two private data members, in other implementations they do something else.
If possible, though, give the class the functionality that the user needs, so that they don't need public data or accessors. An example in the standard libraries is std::stack
, which has a protected data member for use by derived classes, but does not give "normal" users any direct access to it. If you find yourself routinely writing accessors for most data members of most classes you write, then you should seriously consider whether your design can be improved. Accessors mean that users of your class must provide the logic to use the data member. But the main advantage of classes is the ability to keep the logic for using data in the same place that the data is defined. If users always provide the logic then you're not using that opportunity.
By the way, there are a couple of errors in your question:
this is class, not a struct
It is a struct. It is also a class type.
int getW() { return w; }
Getters should be const functions: int getW() const { return w; }