Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

No public class members?

101 views
Skip to first unread message

JiiPee

unread,
Dec 10, 2014, 7:17:30 PM12/10/14
to
Sutter keeps saying that "never use public members, but instead
gettes/setters. Only if its a struct type bundling together data and no
functionality". So he seems to say never publics....

Lets see Point-class:

a)
class CPoint
{
public:
int x;
int y;
};

b)
class Point
{
public:
int& X() { return x; }
int& Y() { return y; }
private:
int x;
int y;
};

Now Point will have many member functions as well, thus according to
Sutter we should do b). But what would you guys prefer? On the one hand
Point is a very simple structure and we would rather like to make calls
like: pt.x rather than pt.X(). But on the other hand having X() would
make it easier to debug plus we can later add more stuff inside getter
if needed, for example:

class Point
{
public:
int& X()
{
++xCallCount;
return x;
}
int& Y() { return y; }
private:
int x;
int y;
int xCallCount = 0;
};

(to know how many times x has been called).
But seems to me that most library implementators prefer 1) version, even
Microsoft.

So a poll: how many or you chose a) and how man b)??

JiiPee

unread,
Dec 10, 2014, 7:18:37 PM12/10/14
to
Ups.... was meant to say "No public member variables".

Ian Collins

unread,
Dec 10, 2014, 7:24:26 PM12/10/14
to
I prefer c: If it's a POD, use public members, if not only expose const
members.

--
Ian Collins

Christopher Pisz

unread,
Dec 10, 2014, 7:29:34 PM12/10/14
to
I figure 1) Carry over from C 2) Lazy 3)They don't care
Microsoft breaks so many rules, that I would never ever cite them as an
example of how to code, not even with the languages they made up themselves.

> So a poll: how many or you chose a) and how man b)??

You only mentioned "functionality" as the determining factor, but I'd
make the decision based on whether there exists any method that would
mutate the class data.

If I've got

struct Point
{
Point(int x, y)
int GetArea();

int m_x;
int m_y;
}

I'd go with struct and public

If I wanted to add void ShrinkBy(int amount, bool heightOrWidth)
I'd go with protected/private and class.


Ian Collins

unread,
Dec 10, 2014, 7:34:05 PM12/10/14
to
I assume you meant to write

int GetArea() const;

>
> int m_x;
> int m_y;
> }
>
> I'd go with struct and public
>
> If I wanted to add void ShrinkBy(int amount, bool heightOrWidth)
> I'd go with protected/private and class.

--
Ian Collins

JiiPee

unread,
Dec 10, 2014, 7:35:25 PM12/10/14
to
Because Point needs many member functions, thus you would do then X().

Many professionals do public members though. For example famous SFML
graphics library does:

class Rect <cid:part1.07010...@notvalid.com>
{
public:
... many functions
// Member data
T left <cid:part2.04090...@notvalid.com>;
T top <cid:part3.09010...@notvalid.com>;
T width <cid:part4.09000...@notvalid.com>;
T height <cid:part5.02030...@notvalid.com>;
};

And Visual Studio also doing it.

JiiPee

unread,
Dec 10, 2014, 7:35:54 PM12/10/14
to
Do you think they are wrong by doing this?

JiiPee

unread,
Dec 10, 2014, 7:41:08 PM12/10/14
to
Ok, but how about the issues of being able to debug x and y, plus being
able later on extend the class? You don't see them problems? Am actually
thinking about this as I need to create Rect and Point to my library :).
But I do not really like to write pt.X(). Its just pain it the code. And
pt.x looks even better. But true, pt.X() has its benefits....

Ian Collins

unread,
Dec 10, 2014, 7:44:04 PM12/10/14
to
JiiPee wrote:
> On 11/12/2014 00:35, JiiPee wrote:
>> On 11/12/2014 00:24, Ian Collins wrote:
>>>
>>> I prefer c: If it's a POD, use public members, if not only expose
>>> const members.
>>>
>>
>> Because Point needs many member functions, thus you would do then X().

In my case:

int x() const;

I doubt I'd ever return a public member by reference, that's no
different to having a public member.

I agree with what Christopher Pisz wrote and I would extend my original
to include classes with const qualified member functions.

>> Many professionals do public members though. For example famous SFML
>> graphics library does:
>>
>> class Rect <cid:part1.07010...@notvalid.com>
>> {
>> public:
>> ... many functions
>> // Member data
>> T left <cid:part2.04090...@notvalid.com>;
>> T top <cid:part3.09010...@notvalid.com>;
>> T width <cid:part4.09000...@notvalid.com>;
>> T height <cid:part5.02030...@notvalid.com>;
>> };
>>
>> And Visual Studio also doing it.
>
> Do you think they are wrong by doing this?
>

If they have non-const member functions, yes.

--
Ian Collins

Ian Collins

unread,
Dec 10, 2014, 7:46:41 PM12/10/14
to
Ian Collins wrote:
> JiiPee wrote:
>> On 11/12/2014 00:35, JiiPee wrote:
>>> On 11/12/2014 00:24, Ian Collins wrote:
>>>>
>>>> I prefer c: If it's a POD, use public members, if not only expose
>>>> const members.
>>>>
>>>
>>> Because Point needs many member functions, thus you would do then X().
>
> In my case:
>
> int x() const;
>
> I doubt I'd ever return a public member by reference, that's no
> different to having a public member.

I doubt I'd ever return a *private* member by reference
--
Ian Collins

JiiPee

unread,
Dec 10, 2014, 7:47:53 PM12/10/14
to
On 11/12/2014 00:43, Ian Collins wrote:
> JiiPee wrote:
>> On 11/12/2014 00:35, JiiPee wrote:
>>> On 11/12/2014 00:24, Ian Collins wrote:
>>>>
>>>> I prefer c: If it's a POD, use public members, if not only expose
>>>> const members.
>>>>
>>>
>>> Because Point needs many member functions, thus you would do then X().
>
> In my case:
>
> int x() const;

yes true, thats better, even looks better. And member could be: int m_x;

>
> I doubt I'd ever return a public member by reference, that's no
> different to having a public member.

But it would still have 2 benefits: 1) can be debugged, 2) can add code
inside getters. So I would not say its no different, but you could say
its not essentially different.

JiiPee

unread,
Dec 10, 2014, 7:49:15 PM12/10/14
to
Sutter suggested that that would be better than putting member variable
public. Its doing the same job plus the 2 things I mentioned.

JiiPee

unread,
Dec 10, 2014, 7:55:24 PM12/10/14
to
So far all libraries I have checked (3-4) use public x and y. For
example b2Vec2 in physics library Box2D also doing it. So seems like
putting them public seems to be prefered among library makers

Ian Collins

unread,
Dec 10, 2014, 8:11:29 PM12/10/14
to
Care to explain "can be debugged"?

--
Ian Collins

JiiPee

unread,
Dec 10, 2014, 8:22:17 PM12/10/14
to
void Point::setX(int x)
{
m_x = x;
}

Lets say we have a very large code and we know that the problem is that
some line is setting x to zero (we cannot divide by zero). We do not
know who set it to 0. But we can put a code temporary inside:

void Point::setX(int x)
{
if(x == 0)
cout<<"error";
m_x = x;
}

Now, we cannot do the same if we set m_x as a public member variable.

Ian Collins

unread,
Dec 10, 2014, 8:26:21 PM12/10/14
to
JiiPee wrote:
> On 11/12/2014 01:11, Ian Collins wrote:
>> JiiPee wrote:
>>> On 11/12/2014 00:43, Ian Collins wrote:
>>>> JiiPee wrote:
>>>>> On 11/12/2014 00:35, JiiPee wrote:
>>>>>> On 11/12/2014 00:24, Ian Collins wrote:
>>>>>>>
>>>>>>> I prefer c: If it's a POD, use public members, if not only expose
>>>>>>> const members.
>>>>>>>
>>>>>>
>>>>>> Because Point needs many member functions, thus you would do then
>>>>>> X().
>>>>
>>>> In my case:
>>>>
>>>> int x() const;
>>>
>>> yes true, thats better, even looks better. And member could be: int m_x;
>>>
>>>>
>>>> I doubt I'd ever return a public member by reference, that's no
>>>> different to having a public member.
>>>
>>> But it would still have 2 benefits: 1) can be debugged, 2) can add code
>>> inside getters. So I would not say its no different, but you could say
>>> its not essentially different.
>>
>> Care to explain "can be debugged"?
>>
>
> void Point::setX(int x)
> {
> m_x = x;
> }

That isn't a getter...

--
Ian Collins

Paavo Helde

unread,
Dec 11, 2014, 2:04:26 AM12/11/14
to
JiiPee <n...@notvalid.com> wrote in news:2l6iw.166444$td6....@fx30.am4:

> On 11/12/2014 01:11, Ian Collins wrote:
>> Care to explain "can be debugged"?
>>
>
> void Point::setX(int x)
> {
> m_x = x;
> }
>
> Lets say we have a very large code and we know that the problem is
> that some line is setting x to zero (we cannot divide by zero). We do
> not know who set it to 0.

Debugging can be done with a public variable as well, just set up a data
breakpoint on the needed memory address, with a suitable condition.

In general, public variables can be used if there are no constraints or
class invariants. With a point class, this would mean that x and y are
independent and can take any values. If zero values are prohibited, this
is already an invariant and instead of a public variable there should be
getters and setters which assert the invariant. Or alternatively, instead
of the plain int the public member variables could be of a user-defined
class like NonZeroInt, which have their own assignment and conversion
operators checking this invariant.

For libraries, it is also important to make the usage as simple as
possible, and to avoid any suspicions (unfounded or not) that there might
appear performance problems. So I am not surprised they are using public
members.

Cheers
Paavo

JiiPee

unread,
Dec 11, 2014, 3:09:28 AM12/11/14
to
On 11/12/2014 07:04, Paavo Helde wrote:
> JiiPee <n...@notvalid.com> wrote in news:2l6iw.166444$td6....@fx30.am4:
>
>> On 11/12/2014 01:11, Ian Collins wrote:
>>> Care to explain "can be debugged"?
>>>
>> void Point::setX(int x)
>> {
>> m_x = x;
>> }
>>
>> Lets say we have a very large code and we know that the problem is
>> that some line is setting x to zero (we cannot divide by zero). We do
>> not know who set it to 0.
> Debugging can be done with a public variable as well, just set up a data
> breakpoint on the needed memory address, with a suitable condition.

oh, I have never done that myself. I ll have to check that...So why
Sutter and guys then say debugging is easier with functions?Surely they
know what you said...
But lets say you want to print/log to a file also something when x==0,
that would not be possible I guess? For that we would need the setX
-function.

"In general, public variables can be used if there are no constraints or
class invariants. With a point class, this would mean that x and y are
independent and can take any values. If zero values are prohibited, this
is already an invariant and instead of a public variable there should be
getters and setters which assert the invariant. Or alternatively,
instead of the plain int the public member variables could be of a
user-defined class like NonZeroInt, which have their own assignment and
conversion operators checking this invariant. For libraries, it is also
important to make the usage as simple as possible, and to avoid any
suspicions (unfounded or not) that there might appear performance
problems. So I am not surprised they are using public members."

This makes sense, and I am also taking that route to putting them as
publics. I guess one has to find a balance when to do it and when
not.... plus I do not think there is any definite truth here. Its a bit
a matter of taste as well I guess. But if most of the professionals use
in libs publics here, then I guess its good to follow them...they all
have been thinking about this and did their desisions.





Christopher Pisz

unread,
Dec 11, 2014, 11:03:33 AM12/11/14
to
Debugging x and y is part of what led me to my decision. If there are no
public mutators then there is only one way that m_x and m_y could be
changed after the Point is constructed. So I can either search for .m_x=
and m_x =, or if I have a fancy debugger just tell it to stop when the
contents of the address where m_x lives are changed.

On the other hand, If I had made it a class than I break inside the
mutators.

As far as extension. If there is a good chance Point is going to be
extended then I make it a class to begin with. I suppose that relies on
some information about the project I am writing the Point for. When I
ask myself, "is this a candidate for being a POD?" the need to extend it
come into play.

But to me, this kind of thing isn't a huge decision with the handy dandy
find and replace features of most IDEs, it is simple enough to change
the struct to a class later if need be and change .m_x= and .m_x = to .SetX(


Mr Flibble

unread,
Dec 11, 2014, 12:06:19 PM12/11/14
to
What you present in b) is neither a getter or a setter and practically
has no difference to public member variables. Getter/setter would be:

int X() const { return x; }
void setX(int aX) { x = aX; }

/Flibble

Mr Flibble

unread,
Dec 11, 2014, 12:09:00 PM12/11/14
to
On 11/12/2014 00:17, JiiPee wrote:
All member variables that contribute to a class's invariant should be
private modulo const member variables.

/Flibble

Öö Tiib

unread,
Dec 11, 2014, 1:04:10 PM12/11/14
to
On Thursday, 11 December 2014 10:09:28 UTC+2, JiiPee wrote:
> On 11/12/2014 07:04, Paavo Helde wrote:
> > JiiPee <n...@notvalid.com> wrote in news:2l6iw.166444$td6....@fx30.am4:
> >
> >> On 11/12/2014 01:11, Ian Collins wrote:
> >>> Care to explain "can be debugged"?
> >>>
> >> void Point::setX(int x)
> >> {
> >> m_x = x;
> >> }
> >>
> >> Lets say we have a very large code and we know that the problem is
> >> that some line is setting x to zero (we cannot divide by zero). We do
> >> not know who set it to 0.
> > Debugging can be done with a public variable as well, just set up a data
> > breakpoint on the needed memory address, with a suitable condition.
>
> oh, I have never done that myself. I ll have to check that...So why
> Sutter and guys then say debugging is easier with functions?Surely they
> know what you said...
> But lets say you want to print/log to a file also something when x==0,
> that would not be possible I guess? For that we would need the setX
> -function.

Indeed, if you want to write some run-time sanity checks or debug
tracing or logging for (at least some of) occasions when value of
member changes (or is read) then that sort of debugging is easiest to
do with accessor functions. I trust that is what Sutter had in mind.

> "In general, public variables can be used if there are no constraints or
> class invariants. With a point class, this would mean that x and y are
> independent and can take any values. If zero values are prohibited, this
> is already an invariant and instead of a public variable there should be
> getters and setters which assert the invariant. Or alternatively,
> instead of the plain int the public member variables could be of a
> user-defined class like NonZeroInt, which have their own assignment and
> conversion operators checking this invariant. For libraries, it is also
> important to make the usage as simple as possible, and to avoid any
> suspicions (unfounded or not) that there might appear performance
> problems. So I am not surprised they are using public members."
>
> This makes sense, and I am also taking that route to putting them as
> publics. I guess one has to find a balance when to do it and when
> not.... plus I do not think there is any definite truth here. Its a bit
> a matter of taste as well I guess. But if most of the professionals use
> in libs publics here, then I guess its good to follow them...they all
> have been thinking about this and did their desisions.

On general case neither public accessor member functions nor public
member data do make sense. Every mutable member is usually related
with rest of the data that is managed by class. There are always
dependencies. Exposing it results that the class has effectively
dropped responsibility to manage its data.

For example about such dependencies imagine that "std::vector" had ...
3 getters: 'get_start()', 'get_finish()', 'get_end_of_storage()'
and 3 setters: 'set_start(s)', 'set_finish(f)', 'set_end_of_storage(e)'.
That is it. What else you need? It is all data members it has.
Indeed, such "vector" would be worthless. The classes that have lot
of getters and setters tend to be as worthless as rule.

Jorgen Grahn

unread,
Dec 11, 2014, 3:20:12 PM12/11/14
to
On Thu, 2014-12-11, JiiPee wrote:
...
> So far all libraries I have checked (3-4) use public x and y. For
> example b2Vec2 in physics library Box2D also doing it. So seems like
> putting them public seems to be prefered among library makers

But we're not library makers. Most classes we write will only be used
by other code which is under our control, so it's easy for us to
change the interface when needed.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Juha Nieminen

unread,
Dec 15, 2014, 3:53:16 AM12/15/14
to
JiiPee <n...@notvalid.com> wrote:
> int& X() { return x; }
> int& Y() { return y; }

Those aren't getters and setters. Those are direct access to member
variables, which nullifies the entire idea. Getters and setters
would be:

int x() { return mX; }
int x(int value) { return mX = value; }
int y() { return mY; }
int y(int value) { return mY = value; }

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Tobias Müller

unread,
Dec 23, 2014, 1:37:19 AM12/23/14
to
Paavo Helde <myfir...@osa.pri.ee> wrote:

> Debugging can be done with a public variable as well, just set up a data
> breakpoint on the needed memory address, with a suitable condition.

Data breakpoints are not nearly as convenient as 'normal' breakpoints IME.
Often they are valid only in a single run, especially if ASLR is turned on
(now standard on Windows).
Also data breakpoints are only valid for a _single_ instance of the class.
While code breakpoints break for _every_ instance.

Tobi

Paavo Helde

unread,
Dec 23, 2014, 2:46:19 AM12/23/14
to
=?UTF-8?Q?Tobias=20M=C3=BCller?= <tro...@bluewin.ch> wrote in
news:1569487410440962347.83...@news.eternal-september.
org:

> Paavo Helde <myfir...@osa.pri.ee> wrote:
>
>> Debugging can be done with a public variable as well, just set up a
>> data breakpoint on the needed memory address, with a suitable
>> condition.
>
> Data breakpoints are not nearly as convenient as 'normal' breakpoints
> IME.

That's true, but this is more of a tool problem.

> Often they are valid only in a single run, especially if ASLR is
> turned on (now standard on Windows).

... or if multiple threads and dynamic allocation are in play.

> Also data breakpoints are only valid for a _single_ instance of the
> class. While code breakpoints break for _every_ instance.

Often, a specific instance is what I want. Also, tracking every instance
would be in principle also possible for a tool, it amounts to adding a
special breakpoint in each constructor of the class which adds a new data
breakpoint in the constructed object. One potential problem with this
approach is that IIRC the number of hardware data breakpoints is very
limited and emulating them via protected virtual memory pages may turn
the program rather slow.

On the other hand, data breakpoints can be really helpful in tracking
down some obscure errors, like the initialization function of PHP DLL
writing over some bytes in some static data array in another totally
unrelated library.

Cheers
Paavo
0 new messages