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

style: static data member vs. file scope static

24 views
Skip to first unread message

zengmin

unread,
Jan 25, 1998, 3:00:00 AM1/25/98
to

I'm wandering which of the following is prefered:
1)
// foo.h
class foo {
private:
static int _foodata;
public:
...
};
// foo.cpp
int foo::_foodata;

2)
// foo.h
class foo {
public:
...
};
// foo.cpp
static int _foodata;

note foodata is private data member and is accessed only by foo member
functions.
1) seems to be 'logically' more reasonable, but 2) makes the implementation
more independant, I don't need to change the header file if I changed
implementation and _foodata is no longer needed.

thanks in advance
zengmin

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Mark Wilden

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

zengmin wrote in message <6afe86$6...@netlab.cs.rpi.edu>...

>2)
>// foo.h
>class foo {
>public:
> ...
>};
>// foo.cpp
>static int _foodata;


Since _foodata is at file scope, you have two problems: anything in
the file can access it, and anything not in the file (like other foo
member functions) can't.

Nathan Myers

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

In article <6afe86$6...@netlab.cs.rpi.edu>, zengmin <zen...@usa.net> wrote:
>
>struct foo { static int _foodata; };

Be warned that names that start with an underscore are likely
to suffer assault by your compiler and its runtime system.
Avoid using such names, and names with double-underscore
in them.

It is useful to distinguish member names. Two popular conventions are
exemplified by:

foodata_
foodataM

Nathan Myers
n...@nospam.cantrip.org http://www.cantrip.org/

(In answer to the original question: a static member makes it easier
for you to move functions from one source file to another. That's all.)

alpha

unread,
Jan 26, 1998, 3:00:00 AM1/26/98
to

I'm wandering which of the following is prefered:
1)
// foo.h
class foo {
private:
static int _foodata;
public:
...
};
// foo.cpp
int foo::_foodata;

2)


// foo.h
class foo {
public:
...
};
// foo.cpp
static int _foodata;

note foodata is private data member and is accessed only by foo member


functions.
1) seems to be 'logically' more reasonable, but 2) makes the implementation
more independant, I don't need to change the header file if I changed
implementation and _foodata is no longer needed.

thanks in advance
zengmin


Tim Ottinger

unread,
Jan 30, 1998, 3:00:00 AM1/30/98
to


Nathan Myers wrote:

> It is useful to distinguish member names. Two popular conventions are
> exemplified by:
>
> foodata_
> foodataM

Not to mention its* my* and the noteworthy habit of always qualifying
members with this->. I learned to like the latter reading Doug Schmidt
and friends' ACE Wrappers. My current employer likes 'ItsWhatever'.

With the this-> habit, you don't need a naming convention. But you
still need code reviews.

tim

David Vandevoorde

unread,
Jan 30, 1998, 3:00:00 AM1/30/98
to

Tim Ottinger wrote:
[...]

> With the this-> habit, you don't need a naming convention. But you
> still need code reviews.

The `this->' convention also ensures that the designated
name is dependent if you're in a template definition.
In turn, that guarantees that the name won't be looked
up until instantiation time and that it will also be
looked up in dependent base classes and not in namespace
scopes.

Generally speaking, all those properties are desirable
for member names.

Daveed

Mark Wilden

unread,
Jan 30, 1998, 3:00:00 AM1/30/98
to

Tim Ottinger wrote in message <6ascli$e...@netlab.cs.rpi.edu>...

>
>With the this-> habit, you don't need a naming convention. But you
>still need code reviews.

You also don't need to bother thinking up special names for function
arguments:

class C {
int height;
public:
void setHeight(int height) { this->height = height; }

// but note:
C(int height) : height(height) {}
};

Bradd W. Szonye

unread,
Jan 31, 1998, 3:00:00 AM1/31/98
to

>Tim Ottinger wrote in message <6ascli$e...@netlab.cs.rpi.edu>...

>>With the this-> habit, you don't need a naming convention. But you
>>still need code reviews.
>

Mark Wilden wrote in message <6atm4g$o...@netlab.cs.rpi.edu>...

>You also don't need to bother thinking up special names for function
>arguments:
>
> class C {
> int height;
> public:
> void setHeight(int height) { this->height = height; }
> // but note:
> C(int height) : height(height) {}
> };

Is that last line a problem? I'm not sure. But there still is one other
problem: I strongly prefer naming accessors the same as data members; I
only use "verbs" for procedures and mutators. (In other words, I hate
"int C::getHeight() const;").

int C::height() const;

does not fit in well unless you name the corresponding actual data
member something different.

Bradd W. Szonye
bra...@concentric.net
http://www.concentric.net/~Bradds

Bradd W. Szonye

unread,
Jan 31, 1998, 3:00:00 AM1/31/98
to

David Vandevoorde wrote in message <6atlk7$n...@netlab.cs.rpi.edu>...
>
>The `this->' convention [for naming member data inside
>member functions] also ensures that the designated

>name is dependent if you're in a template definition.
>In turn, that guarantees that the name won't be looked
>up until instantiation time and that it will also be
>looked up in dependent base classes and not in namespace
>scopes.
>
>Generally speaking, all those properties are desirable
>for member names.

The only trouble I frequently have in naming class members is the need
for naming something three different ways:

class foo {
public:
foo(T member);
T member() const;
foo & set_member(T member);
private:
T member; // naming clash with arguments/accessors
};

The three ways are: as argument, as accessor, and as member data.
There's often no conflict between arguments and accessors, since it's
mostly mutators that take arguments, and mutators don't always need to
call the accessor. (In other words, using an accessor name as an
argument name hides the accessor, but that's okay if you don't use it.)
However, you can't use the same name for accessor and member, however
desirable that may be. Instead, you do something like this:

class foo {
public:
foo(T a_member);
T member() const;
foo & set_member(T a_member);
private:
T x_member;
};

... where "a_" and "x_" follow some project convention. While "this->"
is a viable substitute for "x_" in some contexts, there's still a need
to differentiate the data name from the accessor name. Once you've done
that, it seems strange or redundant to use "this->x_member," although I
think it's still a good idea, and I may start using this idiom in my own
code.

One minor annoyance:

foo::copy(foo const & that) { this->x_member = that.x_member; }

It's just one more reason to wish that BS had invented references before
"this." On a smart enough compiler, you could possibly use:

class bar {
public: bar(): me(*this) { }
private: bar & me;
};

... but the majority of compilers probably wouldn't realize that no
space is necessary for the "me" reference. Also, unfortunately, the best
name for "me" (i.e., "this") is already taken. Just future notes for
when I create my own programming language someday.

Alf P. Steinbach

unread,
Feb 1, 1998, 3:00:00 AM2/1/98
to

This is very much about preferences, but there are 3 good reasons not
to introduce naming standards just willy-nilly: coding to such
standards is a pain in the arse, it produces unreadable code, and
it uses up time and deflects attention from more important issues
at code review. That certainly goes for "m_" prefixes for members.


Bradd W. Szonye wrote:
> The only trouble I frequently have in naming class members is the need
> for naming something three different ways:
>
> class foo {
> public:
> foo(T member);
> T member() const;
> foo & set_member(T member);
> private:
> T member; // naming clash with arguments/accessors
> };
>
> The three ways are: as argument, as accessor, and as member data.

Since it's often natural to use the same name for a type and an
instance of that type, a suffix like "_t" or "_type" for types has
value. I would do the code above as follows:


class foo_t
{

// Construction & destruction:
public:

foo_t( T const &a_member );
virtual ~foo_t();


// Accessors:
public:

T Member() const;


// Modifiers:
public:

foo_t& SetMember( T const &a_member );


// State:
private:

T member;
}; // foo_t


The "a_"/"an_" convention is not strictly necessary, but is convenient
for reading the code.

Using initial uppercase for function names is part of a general
convention whereby names are placed into three *non-overlapping* sets:
macros, functions, and everything else. Especially placing macro
names (where I use all uppercase) in a set by itself is important to
avoid unintentional macro expansions. Differentiating between
functions and data makes it easy to see which of "x = value;" and
"x = Value();" should be used -- it may be the case that
"x = Value;" will compile even though Value is a function.

Using "Member" instead of "GetMember" is just to improve readability.
In general, I feel names should be chosen with *usage* in mind. E.g.,
an expression like "5 * GetSin( x )" is an abomination.

Overriding criterion for all such rules: as few of them as possible!

- Alf

David A. Cuthbert

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

Bradd W. Szonye <bra...@concentric.net> wrote:
>The only trouble I frequently have in naming class members is the need
>for naming something three different ways:
>
> class foo {
> public:
> foo(T member);
> T member() const;
> foo & set_member(T member);
> private:
> T member; // naming clash with arguments/accessors
> };
>
>The three ways are: as argument, as accessor, and as member data.
[...]

>However, you can't use the same name for accessor and member, however
>desirable that may be. Instead, you do something like this:
[rename "T member" to "T x_member"]

Why so much trouble? Why not do something like:

struct FooImpl {
private:
T member;

friend class Foo;
};

class Foo {
public:
// your methods here

private:
FooImpl Impl; // or struct FooImpl *Impl; if you want the
// pimpl idiom
};

T Foo::member() { return Impl.member; }


I "stumbled" across this when I moved a class using the pimpl idiom to
a standard class (the repeated dynamic allocations were killing
performance in a critical loop). It did involve a search and replace
on Impl-> to Impl. in the implementation source file, but that was
surprisingly painless.
--
David A. Cuthbert (da...@ece.cmu.edu)
Graduate Student Electrical and Computer Engineering
Data Storage Systems Center, Carnegie Mellon University

Julian Macri

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

I would like to add one other thing to this thread. From an OO point of
view (certainly a Smalltalk point of view) aren't we taught that it is
better to always use a getter method to get a member variable:

this->member()

Stefan Rupp

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

Good morning,

n...@nospam.cantrip.org (Nathan Myers) writes:
> In article <6afe86$6...@netlab.cs.rpi.edu>, zengmin <zen...@usa.net> wrote:
> >struct foo { static int _foodata; };
>
> Be warned that names that start with an underscore are likely
> to suffer assault by your compiler and its runtime system.
> Avoid using such names, and names with double-underscore
> in them.

This is an often stated argument, but actually I don't think it's true.

As stated in section 2.10 of the CD2

In addition, identifiers containing a double underscore (__) or begin-
ning with an underscore and an upper-case letter are reserved for use
by C++ implementations and standard libraries and shall not be used
otherwise; no diagnostic is required.

And again in section 17.3.3.1.2:

Each name that begins with an underscore and either an uppercase
letter or another underscore is reserved to the implementation for
any use.

OK, that doesn't affect any identifier starting with an underscore and a
lower-case letter. Later on in the same section:

Each name that begins with an underscore is reserved to the imple-
mentation for use as a name with file scope or within the namespace
std in the ordinary name space.

You may refer this paragraph, but this affects only names at file scope.
But data member names are NOT at file scope, so I don't see any reason
not to allow data members of a class beginning with an underscore and a
lower-case letter.

Am I missing something?

Ciao,
struppi

--
Stefan H. Rupp
Geodaetisches Institut der RWTH Aachen Email: str...@acm.org
Templergraben 55, D-52062 Aachen, Germany Tel.: +49 241 80-5295

Nathan Myers

unread,
Feb 2, 1998, 3:00:00 AM2/2/98
to

Alf P. Steinbach <al...@online.no> wrote:
>This is very much about preferences, but there are 3 good reasons not
>to introduce naming standards just willy-nilly: coding to such
>standards is a pain in the arse, it produces unreadable code, and
>it uses up time and deflects attention from more important issues
>at code review. That certainly goes for "m_" prefixes for members.

The consensus among experts is that members need to be distinguished
from other names. (This is regardless of whether you use a "this->"
prefix.) An "m_" prefix, an "M" suffix, an "_" suffix are all
possibilities. After a lot of experience I have found I prefer a
suffix.

(This does not imply any preference for the (misnamed) "Hungarian
notation" that mixes a variable's type into its name. Code written
that way should be taken out and shot. (If you disagree, I don't
care to hear about it.))

>Bradd W. Szonye wrote:
>> The only trouble I frequently have in naming class members is the need
>> for naming something three different ways:
>>
>> class foo {
>> public:
>> foo(T member);
>> T member() const;
>> foo & set_member(T member);
>> private:
>> T member; // naming clash with arguments/accessors
>> };
>>
>> The three ways are: as argument, as accessor, and as member data.

A consistent, minimal system is:
Member data and constants are be distinguished with a prefix or
suffix, mainly because of namespace pollution by C headers, and
(like member function names) always more than three letters long.
Argument and local variable names need be no more than three letters
long because the number of such names in any scope is very tiny.
Type names begin with a Capital letter. This is all the distinction
among names needed until you get to namespaces. Probably namespace
names will need a suffix, like "SignalLib".

ALL_CAPS names are reserved for macros, period.

>Overriding criterion for all such rules: as few of them as possible!

As few as necessary, anyway.

Pete Becker

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

Nathan Myers wrote:
>
> Alf P. Steinbach <al...@online.no> wrote:
> >This is very much about preferences, but there are 3 good reasons not
> >to introduce naming standards just willy-nilly: coding to such
> >standards is a pain in the arse, it produces unreadable code, and
> >it uses up time and deflects attention from more important issues
> >at code review. That certainly goes for "m_" prefixes for members.
>
> The consensus among experts is that members need to be distinguished
> from other names.

Well, some experts agree with that, but it's far from a concensus. Many
disagree.
-- Pete

Alf P. Steinbach

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

Nathan Myers wrote:
>
> Alf P. Steinbach <al...@online.no> wrote:
> >This is very much about preferences, but there are 3 good reasons not
> >to introduce naming standards just willy-nilly: coding to such
> >standards is a pain in the arse, it produces unreadable code, and
> >it uses up time and deflects attention from more important issues
> >at code review. That certainly goes for "m_" prefixes for members.
>
> The consensus among experts is that members need to be distinguished
> from other names.

I would be interested in learning more about this, since I fail to
see that such a prefix carries any information whatsoever. E.g.,
what information is carried by "m_" in "rect.m_height"? Or in
"m_height = bottom - top", where you either understand the code
without the m_, or don't understand a thing? Zero or negative
info content prefixes is part of what I meant by willy-nilly.


> (This is regardless of whether you use a "this->"
> prefix.)

At least, that is a compiler checkable form, and much preferable
to possibly misguiding non-checkable prefixes.

> An "m_" prefix, an "M" suffix, an "_" suffix are all
> possibilities. After a lot of experience I have found I prefer a
> suffix.

That is a good reason for using a convention. I would probably
have no difficulty reading your code, and you find it more readable
with that convention. But then we're into *personal preferences*.



> (This does not imply any preference for the (misnamed) "Hungarian
> notation" that mixes a variable's type into its name. Code written
> that way should be taken out and shot. (If you disagree, I don't
> care to hear about it.))

Well I agree completely. Some reasons (not at all an exhaustive list!):


* Hungarian notation severely reduces readability.

* The physical type of a variable may have little to do with its
purpose, thus, Hungarian notation may in many cases be misleading.

* Ensuring that correct Hungarian notation is used increases coding
time.

* Checking the correctness of Hungarian notation increases code review

time.

* Hungarian notation deflects attention and time from more important
issues at code review.

* The physical type of a variable may change as the code evolves
(prime
example is "lpsz", there's no such thing as long pointer in std
C++).

* The Hungarian notation prefixes are meta-information not subject
to
compiler checking, hence, relying on this information may/will lead
to
bugs (logical preconditions or postconditions should be expressed
explitly, e.g. as assertions).

The last point may not be obvious, but one example I've encountered is,
again, the "lpsz" or "sz" prefix, which implies a zero-terminated
string, which is not necessarily what that char array contains. Cost
me several hours to find that darned bug, all because of a misleading
prefix (only present because the coding standard required it). Urgh.


- Alf

John Potter

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

Julian Macri <luvm...@us.ibm.com> wrote:

: I would like to add one other thing to this thread. From an OO point


of
: view (certainly a Smalltalk point of view) aren't we taught that it is
: better to always use a getter method to get a member variable:

: this->member()

If it were always, the getter could not be written ;-P Smalltalk
access is by object and C++ access is by type (class). The choices
are different and that is all. That sometimes causes some confusion
on the inability to access members of a base class object when it is
possible to access the base class members of this object.

John

Nathan Myers

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

Stefan Rupp <str...@gia.rwth-aachen.de> wrote:

>n...@nospam.cantrip.org (Nathan Myers) writes:
>> Be warned that names that start with an underscore are likely
>> to suffer assault by your compiler and its runtime system.
>> Avoid using such names, and also names with double-underscore

>> in them.
>
>This is an often stated argument, but actually I don't think it's true.
>As stated in section 2.10 of the CD2 ...
>And again in section 17.3.3.1.2: ...
>
>Am I missing something?

Yes: buggy implementations. It is distressingly common,
particularly in C header files propagated into C++ implementations,
for macros to be defined with names like "_this". It's strictly
in violation of various standards, but somehow that doesn't seem
to matter.

An alternative to avoiding such names is to say
#undef _name
in the header where you use such a name, but that adds clutter.

The point is that standards tell you a lot of what you need to
know to write portable code, but they don't tell you everything.

J. Kanze

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

Stefan Rupp <str...@gia.rwth-aachen.de> writes:

|> n...@nospam.cantrip.org (Nathan Myers) writes:
|> > In article <6afe86$6...@netlab.cs.rpi.edu>, zengmin <zen...@usa.net> wrote:
|> > >struct foo { static int _foodata; };
|> >

|> > Be warned that names that start with an underscore are likely
|> > to suffer assault by your compiler and its runtime system.

|> > Avoid using such names, and names with double-underscore


|> > in them.
|>
|> This is an often stated argument, but actually I don't think it's true.

[Quotes from standard deleted...]

|> Am I missing something?

Yes. The reality of what compilers and systems actually do.

Your totally correct in so far as the standard is concerned. In
practice, however, there are an enormous number of systems that don't
conform in this respect. And even on those that do conform strictly,
you still generally end up including non-standard headers which don't
necessarily conform.

The rule, as stated, is not dictated uniquely by the standard, but also
by real life experience. (Similarly, I would avoid names like read or
open for global functions, and don't think it wise to use names like
near or far, even if the standard allows it.)

--
James Kanze +33 (0)1 39 23 84 71 mailto: ka...@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orientée objet --
-- Beratung in objektorientierter Datenverarbeitung

Nathan Myers

unread,
Feb 3, 1998, 3:00:00 AM2/3/98
to

In article <6b79g7$s...@netlab.cs.rpi.edu>,

Alf P. Steinbach <al...@online.no> wrote:
>Nathan Myers wrote:
>> Alf P. Steinbach <al...@online.no> wrote:
>> >there are 3 good reasons not to introduce naming standards just
>> >willy-nilly: [good reasons elided]
>> >That certainly goes for "m_" prefixes for members.
>>
>> The consensus among experts is that members need to be distinguished
>> from other names.
>
>I would be interested in learning more about this, since I fail to
>see that such a prefix carries any information whatsoever. E.g.,
>what information is carried by "m_" in "rect.m_height"? Or in
>"m_height = bottom - top", where you either understand the code
>without the m_, or don't understand a thing? Zero or negative
>info content prefixes is part of what I meant by willy-nilly.

Member data names tend to have the same form as global names
coming from C headers. Reading member function code, it is hard
to tell whether a name is coming from class scope or from global
scope. Qualifying uses of global or namespace names ("::")
helps, and qualifying uses of member names with "this->" can
help too. However, both are intrusive and depend on good
discipline by coders and maintainers.

When member data has a distinguished name, coders have no choice
but to use it in a recognizable way. Anyway the result is less
intrusive than the other alternatives.

(Pete Becker pointed out that it is not entirely universal among
experts to prefer to distinguish member data names. Perhaps
"consensus" is too strong a word.)

Tim Ottinger

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to


Alf P. Steinbach wrote:

> I would be interested in learning more about this, since I fail to
> see that such a prefix carries any information whatsoever. E.g.,
> what information is carried by "m_" in "rect.m_height"? Or in
> "m_height = bottom - top", where you either understand the code
> without the m_, or don't understand a thing? Zero or negative
> info content prefixes is part of what I meant by willy-nilly.

Wow, you're harder on this than I am! Cool!

m_ as you know means "member variable, not some global or
local (including parameters)". Likewise some people put "G"
on the front of globals and "K" on the front of constants.

I always claim that the most important part of choosing a
name is to say what the named object is _for_, not where
it comes from, who invented it, or what type it is.

Then these scope things come up. Is scope about type?
No. Is it about what the object is *for*? Well, kinda.
It says where it's declared somewhat, and namespaces
often tell from whom they come.

My second issue is that all names should be pronounceable,
as-written. If you can't pronounce them, you can't carry
on a conversation about them. See my paper at
http://www.oma.com/ottinger/Naming.html for details
of the forces I recognize for naming.

I will tolerate very little manual mangling of names. I
will put up with 'local scope' adornments, though I really
hate the K and G prefixes. For G I can use ::, so I really
don't need it. For K, there is already existing practice in
abundance that does not use it.

If someone *must* use some kind of prefix or suffix for
variables, they should at least pick something pronounceable.
The company I work for tends to use "its". At least I can say
"its height", "its age" and not "emm underscore pee ess zee
...". A name should pass on a concept when spoken. The
listener should not have to gather symbols and translate
mentally. Communication is always the goal for namings.

But that's just how I feel. All opinions are subject to revision
in the face of well-presented, tangible facts to the contrary.

tim

Bradd W. Szonye

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

Alf P. Steinbach wrote in message <6b79g7$s...@netlab.cs.rpi.edu>...
>
>... I fail to see that a [member name prefix]

>carries any information whatsoever. E.g.,
>[What] information is carried by "m_" in "rect.m_height"? ...

>Zero or negative info content prefixes is
>part of what I meant by willy-nilly.

The information that it provides to me is that the variable is a private
member of the class. The more important benefit is that it provides the
member names from clashing with names in the public interface, like
accessors and parameter names.

>At least, the ["this->" prefix] is a compiler checkable


>form, and much preferable
>to possibly misguiding non-checkable prefixes.

Unfortunately, "this->" is not sufficient alone to prevent confusion
between data member "datum" and accessor "datum()," although it does
prevent the clash between parameter names and member names.

Perhaps "m_" for "member" isn't as useful as "p_" for
"private/physical," but a "p" prefix already has established meaning.
Using "i_" for "internal" might make good sense. I personally strongly
dislike single-underscore suffixes because they have little visual
impact and are easily confused with the unadorned name.

The criteria I use for a member prefix or suffix:
1. A one-character wart is not sufficiently distinguishing, especially
when the one character is underscore.
2. The wart should be suggestive of "member," "private," or similar
concept
3. The wart should be as small as possible (without violating rule 1)
4. Whether the wart is a prefix or suffix depends mostly on how the
unabbreviated form reads: size_m for "size member," i_size for "internal
size."

One other (small) benefit of distinguishing member names is that you can
then use a programmable syntax highlighter/beautifier to highlight when
you're working with private data.

Bradd W. Szonye

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

Julian Macri wrote in message <6b56mr$l...@netlab.cs.rpi.edu>...

>I would like to add one other thing to this thread. From an OO point
of
>view (certainly a Smalltalk point of view) aren't we taught that it is
>better to always use a getter method to get a member variable:
>
> this->member()

I agree that that's generally a good practice. (There are times when
your accessor has side-effects or validation routines that you don't
really want to use in member functions; then you might want to bypass
the gate-keepers.) This is another reason I use data member warts. The
public interface (accessor) has a "simple" form of the data name, the
actual physical data has a modified name to indicate that it is an
internal variable. This also prevents clashes between the data members
and accessors.

Bradd W. Szonye

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

>Stefan Rupp <str...@gia.rwth-aachen.de> writes:
>[noting the parts of the standard that reserve names]
>
>|> Am I missing something?
>
J. Kanze wrote in message <6b7bhr$2...@netlab.cs.rpi.edu>...

>Yes. The reality of what compilers and systems actually do.
>
>Your totally correct in so far as the standard is concerned. In
>practice, however, there are an enormous number of systems that don't
>conform in this respect. And even on those that do conform strictly,
>you still generally end up including non-standard headers which don't
>necessarily conform.

Some compilers are especially bad about blasting the namespace.

Suppose a pre-1989 C compiler used "foo" as a keyword. Then, after the
ANSI C standard, they keep the feature as an extension and change the
keyword to "_foo," but also keep the original spelling for
compatibility. Some users point out that "_foo" isn't really a reserved
name, so they also add "__foo" to the trio. They carry over this
behavior into their C++ compilers, since they share a lot of common
code.

Since the compiler works in "extension" mode by default, you get three
reserved words, only one of which is officially reserved. Eventually
enough people complain about "foo," since it's a common identifier name,
so they might remove that spelling, but still keep the intermediate
"_foo" form. This makes the users happy until they use "_foo" as a data
member name.

Julian Macri

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to


John Potter wrote:

> Julian Macri <luvm...@us.ibm.com> wrote:
>
> : I would like to add one other thing to this thread. From an OO point


> of
> : view (certainly a Smalltalk point of view) aren't we taught that it is
> : better to always use a getter method to get a member variable:
>
> : this->member()
>

> If it were always, the getter could not be written ;-P

Of course, the getter method would refer to the member variabledirectly.
But, this would be the only place the member variable is
referenced directly.

> Smalltalk
> access is by object and C++ access is by type (class). The choices
> are different and that is all. That sometimes causes some confusion
> on the inability to access members of a base class object when it is
> possible to access the base class members of this object.
>

Say what?

Vadim Zeitlin

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

On 3 Feb 1998 09:27:28 -0500, Alf P. Steinbach <al...@online.no> wrote:
>I would be interested in learning more about this, since I fail to
>see that such a prefix carries any information whatsoever.

Is it a question? I have some doubts about it because in this case
it contains the answer to itself (you ask what sense it may have but
say in the next line that it has none :-). If the question were
"what are the good reasons to have a special notation for member
variables?", i'd answer itlike this: it allows you to distinguish at
a glance the member vars from the other ones. Another one is that
it solves once and for all the problem of "SetX(int x) { m_x = x; }".

We all have to read sometimes (often) the code written by others.
When you're reading an implementation of Foo::bar function how do
you distinguish the Foo member variables from the global ones or
even the local if the function is a bit long and uses a lot of variables
(ok, it's bad, but you've already seen 100 or 200 line functions,
haven't you?)? This convention just makes the code easier to
understand, that's all. Perhaps it's totally unimportant for you:
than don't use it. But please do consider using it if you want
the others to understand your code easier (and vice versa).

[the hungarian notation discussion snipped. FYI, it has nothing to
do with "m_" notation]

Regards,
VZ

Stefan Rupp

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

Good morning,

n...@nospam.cantrip.org (Nathan Myers) writes:
> >As stated in section 2.10 of the CD2 ...
> >And again in section 17.3.3.1.2: ...
> >
> >Am I missing something?
>
> Yes: buggy implementations.

Well, if that is the only thing ... :) I never ever had any problem
with the leading underscore in my data member names. So I still don't
see any reason to change my favourite naming scheme, i.e. putting an
_ before the data member name and use the name without the underscore
as the get() method (of course in combination with the this-> idiom).

> The point is that standards tell you a lot of what you need to
> know to write portable code, but they don't tell you everything.

But the argument of the _-opponents always was the rule that names
beginning with an underscore are reserved, and that still is not true.

Ciao,
struppi

--
Dipl.-Inform. Stefan H. Rupp


Geodaetisches Institut der RWTH Aachen Email: str...@acm.org
Templergraben 55, D-52062 Aachen, Germany Tel.: +49 241 80-5295

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Alf P. Steinbach

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

Nathan Myers wrote:
> Member data names tend to have the same form as global names
> coming from C headers. Reading member function code, it is hard
> to tell whether a name is coming from class scope or from global
> scope. Qualifying uses of global or namespace names ("::")
> helps, and qualifying uses of member names with "this->" can
> help too. However, both are intrusive and depend on good
> discipline by coders and maintainers.

Ah, then we can put that q to rest. Simply don't use global
variables, or, when you absolutely must, qualify the name.
But I agree that in a shop where global variables are freely
used, the general quality of coding must be very low, so
forcing the coders to follow low-level rules can make sense.


...


> (Pete Becker pointed out that it is not entirely universal among
> experts to prefer to distinguish member data names. Perhaps
> "consensus" is too strong a word.)

Must be, since I don't agree... ;-)


Cheers,


- Alf

Paul Miller

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

"Bradd W. Szonye" <bra...@concentric.net> writes:

>One other (small) benefit of distinguishing member names is that you
can
>then use a programmable syntax highlighter/beautifier to highlight when
>you're working with private data.

We've been using 'm' and 's' as prefixes for normal and static member
variables for awhile now and it works well, as in:

int foo(int index) const
{
return sTable[index + mOffset];
}

Looking at that one line of code makes it explicit where all those
variables are located.

--
Paul T. Miller | pa...@elastic.avid.com
Principal Engineer | Opinions expressed here are my own.
Avid Technology, Inc. Madison - Graphics and Effects Software Group

Herb Sutter

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

"Alf P. Steinbach" <al...@online.no> wrote:
>Nathan Myers wrote:
>> The consensus among experts is that members need to be distinguished
>> from other names.
>
>I would be interested in learning more about this, since I fail to
>see that such a prefix carries any information whatsoever. E.g.,
>what information is carried by "m_" in "rect.m_height"? Or in
>"m_height = bottom - top", where you either understand the code
>without the m_, or don't understand a thing? Zero or negative

>info content prefixes is part of what I meant by willy-nilly.

I wouldn't say that all experts insist on this, but I happen to feel it's
useful and so "trailing underscore for member names" is in our coding
standards. When writing (and especially later reading) code, I often find
it helpful to be able to see easily whether "oh yeah, that's a member" or
not.

I must admit that none of us here really like m_ prefixes, though. But you
have to get used to them if you're doing MFC work... :-)


---
Herb Sutter (mailto:he...@cntc.com)

Current Network Technologies Corp 2695 North Sheridan Way, Suite 150
www.cntc.com www.peerdirect.com Mississauga Ontario Canada L5K 2N6

Alf P. Steinbach

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

Bradd W. Szonye wrote:
>
> Alf P. Steinbach wrote in message <6b79g7$s...@netlab.cs.rpi.edu>...
> >
> >... I fail to see that a [member name prefix]

> >carries any information whatsoever. E.g.,
> >[What] information is carried by "m_" in "rect.m_height"? ...

> >Zero or negative info content prefixes is
> >part of what I meant by willy-nilly.
>
> The information that it provides to me is that the variable is a private
> member of the class. The more important benefit is that it provides the
> member names from clashing with names in the public interface, like
> accessors and parameter names.

Well, as I wrote originally, one should have as few rules as possible,
but one absolute necessity is to distinguish between three non-
overlapping sets of names: macros (all uppercase), functions (your
convention here, I use initial caps), and everything else (your
convention here, I use all lowercase with underscores).

Given this *single rule* -- which is a necessity -- your most
important problem (benefit) disappears, and the code becomes
more readable (or perhaps, just the single word readable) to boot.

Anarchist by birth that I am, I prefer few and simple rules... :-)


Hth. (and not only for C++),


- Alf

John E. Potter

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to


On 4 Feb 1998, Julian Macri wrote:

> John Potter wrote:

> > Julian Macri <luvm...@us.ibm.com> wrote:

> > : I would like to add one other thing to this thread. From an OO
point
> > : of
> > : view (certainly a Smalltalk point of view) aren't we taught that
it is
> > : better to always use a getter method to get a member variable:

> > : this->member()

> > Smalltalk


> > access is by object and C++ access is by type (class). The choices
> > are different and that is all. That sometimes causes some confusion
> > on the inability to access members of a base class object when it is
> > possible to access the base class members of this object.

> Say what?

class B {
protected :
int b;
};
class D : public B {
protected :
int d;
public :
void f (D that, B base) {
this->d = base.b; // 1
this->d = that.b; // 2
this->d = this->b; // 3
}
};

Every Smalltalker knows that 1 is an error because methods may only
access attributes of *this (access is by object). A beginning C++er
does not know that 1 is an error because member functions may access
protected members of their base class part. The last word is what
they do not understand (access is by class). The object base is not
a class D object.

2 is an error in Smalltalk for the same reason as 1 and it is not
an error in C++ because access is to all objects of class D.

3 is not an error in C++ for the same reason as 2. It is also not
an error in Smalltalk because attributes are really protected not
private. Most Smalltalkers do not know this because they always
use accessors and never make the discovery.

Smalltalkers never become confused and remain ignorant. C++ers
get confused because they make the error but, hopefully, learn
form it.

The languages are different and so are the practitioners. The
idioms of one do not always sit well with the users of the other.

John

Alf P. Steinbach

unread,
Feb 4, 1998, 3:00:00 AM2/4/98
to

Vadim Zeitlin wrote:
> i'd answer itlike this: it allows you to distinguish at
> a glance the member vars from the other ones.

*Don't use globals*. Or if you must, qualify them. C++ has the
"::" notation just for that, and it's compiler checkable.


> Another one is that
> it solves once and for all the problem of "SetX(int x) { m_x = x; }".

void SetX( int new_x_value ){ x = new_x_value; } // Or whatever...

>
> We all have to read sometimes (often) the code written by others.
> When you're reading an implementation of Foo::bar function how do
> you distinguish the Foo member variables from the global ones or

*Don't use globals*. Or if you must, qualify them. C++ has the
"::" notation just for that, and it's compiler checkable.


> even the local if the function is a bit long and uses a lot of
variables
> (ok, it's bad, but you've already seen 100 or 200 line functions,
> haven't you?)?

Unfortunately, I have had the unpleasant job of removing bugs from
such code, written in C and Cobol. The lead programmer on that
team was of the opinion that common functionality (like page
buttons for listboxes) was *impossible* to factor out, and had
to be repeated everywhere using code cut and paste. Which of course
multiplied the bugs while also making maintainance very hard.


> ...


> [the hungarian notation discussion snipped. FYI, it has nothing to
> do with "m_" notation]

Mmm, this may not make sense to you, but it's actually all about
readability. The coding standard for the project I mentioned above
was written by the very same lead programmer, and it required HN.
Not surprisingly, the combination of (1) little or no abstraction,
(2) functions with hundreds of lines and (3) HN, really made the
code nice and clean and easy to maintain.


Hth.,

- Alf

Nathan Myers

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to

Tim Ottinger <otti...@oma.com> wrote:
>... all names should be pronounceable,

>as-written. If you can't pronounce them, you can't carry
>on a conversation about them. See my paper at
>http://www.oma.com/ottinger/Naming.html for details
>of the forces I recognize for naming.

An excellent paper. I'm going to add a link on my page.

>If someone *must* use some kind of prefix or suffix for
>variables, they should at least pick something pronounceable.

In "m_foobar" or "foobarM", the decoration is pronounced "member",
as "member foobar". Part of any naming convention that involves
abbreviation should include prescribed pronunciations. A convention
that doesn't admit unambigous pronunciation is a bad one.

Nathan Myers

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to

Stefan Rupp <str...@gia.rwth-aachen.de> wrote:
>n...@nospam.cantrip.org (Nathan Myers) writes:
>> Stefan Rupp <str...@gia.rwth-aachen.de> wrote:
>> >Am I missing something?
>>
>> Yes: buggy implementations.
>
>Well, if that is the only thing ... :) I never ever had any problem
>with the leading underscore in my data member names.

If you don't care about portability, why do you care about
standard conformance at all? If it works with your current
release of your current compiler, go for it; let somebody else
worry about porting to the next release.

Nathan Myers

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to

Alf P. Steinbach <al...@online.no> wrote:
>Nathan Myers wrote:
>> Member data names tend to have the same form as global names
>> coming from C headers.
>
>Ah, then we can put that q to rest. Simply don't use global
>variables, or, when you absolutely must, qualify the name.
>But I agree that in a shop where global variables are freely
>used, the general quality of coding must be very low, so
>forcing the coders to follow low-level rules can make sense.

Most global names are not variables. All names in C headers
are global. "Shops" where no C headers are used are scarce to
nonexistent, and will be for a long time.

Julian Macri

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to


Bradd W. Szonye wrote:

> Julian Macri wrote in message <6b56mr$l...@netlab.cs.rpi.edu>...

> >I would like to add one other thing to this thread. From an OO point
> of
> >view (certainly a Smalltalk point of view) aren't we taught that it
is
> >better to always use a getter method to get a member variable:
> >
> > this->member()
>

> I agree that that's generally a good practice. (There are times when
> your accessor has side-effects or validation routines that you don't
> really want to use in member functions; then you might want to bypass
> the gate-keepers.) This is another reason I use data member warts. The
> public interface (accessor) has a "simple" form of the data name, the
> actual physical data has a modified name to indicate that it is an
> internal variable. This also prevents clashes between the data members
> and accessors.
>

But what if in the future you change the attribute to be calculated or
obtained from some database? Then, all the dozens or hundreds of
places that directly access the member variable will have to be
modified to use the getter method. Using getter methods all the
time, hides the internal implementation and let's you change that
internal implementation with no ripple effects to the rest of the
code.

Julian Macri

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to

Although your explanation is not totally clear, I think I see what
you're
trying to
say. Nevertheless, I've been a Smalltalker for 6 years and a C++'er for
4
years.
I have not had to worry about these access rules too much because I use
getters
and setters everywhere. So, I don't confused about these rules and I
remain

happily ignorant.

Back to the subject of this thread, "member name style", my point about
always
using getters and setters is that whatever member name style you use is
irrelevant
if you always use getters and setters. The member variable will only be
referenced
within the getter and setter.

Also, as I mentioned in a previous append, using getters and setters
encapsulates
the attribute that the instance variable is supposed to represent. If
at
some point,
that attribute needs to be calculated or obtained from some outside
source
(i.e. a
database), then the code change only takes place within the getter and
setter. If
you don't use getters and setters, then the code change may need to
occur in

dozens or hundreds of places.

Doug Harrison

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to

On 30 Jan 1998 17:53:00 -0500, David Vandevoorde <dav...@cup.hp.com>
wrote:

>The `this->' convention also ensures that the designated
>name is dependent if you're in a template definition.
>In turn, that guarantees that the name won't be looked
>up until instantiation time and that it will also be
>looked up in dependent base classes and not in namespace
>scopes.

That reminds me, is the Dec-96 draft's 14.6.2/4 [temp.dep] any
different in the FDIS? The former said that base classes aren't
searched at definition time for non-dependent names in derivations
such as:

template<typename T> struct B : A<T> {};

The D&E described this rule, but as I recall, its example involved a
derivation that looked like:

template<typename T> struct B : T {};

which is very different. I can understand the requirement to use
this-> when deriving from T, but not A<T>.

--
Doug Harrison
dHar...@worldnet.att.net

Michael Furman

unread,
Feb 5, 1998, 3:00:00 AM2/5/98
to

Alf P. Steinbach wrote:
> [...]
>
> Well, as I wrote originally, one should have as few rules as possible,
> but one absolute necessity is to distinguish between three non-
> overlapping sets of names: macros (all uppercase), functions (your
> convention here, I use initial caps), and everything else (your
> convention here, I use all lowercase with underscores).
>
> Given this *single rule* -- which is a necessity -- your most
> important problem (benefit) disappears, and the code becomes
> more readable (or perhaps, just the single word readable) to boot.
>
> Anarchist by birth that I am, I prefer few and simple rules... :-)

I use simillar rules (with some exceptions), but even this small
set (IMO) is redundant and sometimes decrease redability:
1. Good editor (IDE) could use different colors, styles for
different names automatically.
2. Sometimes I don't want names to look differently, for example,
function-style macros and functions!
--
---------------------------------------------------------------
== If you answer, please remove "nospam" from the address
Michael Furman, (603)893-1109
Geophysical Survey Systems, Inc. fax:(603)889-3984
13 Klein Drive engr @ gssi .
P.O. Box 97 mv . com
North Salem, 71543 . 1334 @
NH 03073-0097 compuserve.com
---------------------------------------------------------------

Michael Furman

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Herb Sutter wrote:
>
> "Alf P. Steinbach" <al...@online.no> wrote:
> [...]

> >I would be interested in learning more about this, since I fail to
> >see that such a prefix carries any information whatsoever. E.g.,
> >what information is carried by "m_" in "rect.m_height"? Or in
> >"m_height = bottom - top", where you either understand the code
> >without the m_, or don't understand a thing? Zero or negative

> >info content prefixes is part of what I meant by willy-nilly.
>
> I wouldn't say that all experts insist on this, but I happen to feel it's
> useful and so "trailing underscore for member names" is in our coding
> standards. When writing (and especially later reading) code, I often find
> it helpful to be able to see easily whether "oh yeah, that's a member" or
> not.

IMO, it is useful only in some cases - I name them "low level
programming".
If a code is just a bunch of operators, variables e.t.c. and it is hard
to put them in an intuitive nice model - it is helpful, though good
editor/IDE could do it automatically without changing names.
In case of "high level programming" it is useless (and sometime harmful)
-
addind redundant details can make it harder to understand the
abstraction.

Alf P. Steinbach

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Nathan Myers wrote:
>
> Alf P. Steinbach <al...@online.no> wrote:
> >Nathan Myers wrote:
> >> Member data names tend to have the same form as global names
> >> coming from C headers.
> >
> >Ah, then we can put that q to rest. Simply don't use global
> >variables, or, when you absolutely must, qualify the name.
> >But I agree that in a shop where global variables are freely
> >used, the general quality of coding must be very low, so
> >forcing the coders to follow low-level rules can make sense.
>
> Most global names are not variables.

Then they can't be confused with member variables. Good.
Problem solved.


> "Shops" where no C headers are
> used are scarce to nonexistent, and will be for a long time.

(One such "shop" is the project I'm on right now. We use Java,
C++ and Cobol. No C except standard/compiler C runtime lib.)

You may have a point if you're talking legacy code, not standard
headers. But I think a naming standard reducing readability
is the wrong way to tackle that problem. Two wrongs do not make
one right. Better to wrap those C headers in a namespace, if that
doesn't introduce name mangling (it shouldn't for extern C, but I
may be wrong, if so, correct me -- there must be other solutions).

Cheers,


- Alf

Bradd W. Szonye

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Doug Harrison wrote in message <6bd6s5$5...@netlab.cs.rpi.edu>...
>
>[The] Dec-96 draft's 14.6.2/4 [temp.dep] ...

>said that base classes aren't searched at definition
>time for non-dependent names in derivations such as:
> template<typename T> struct B : A<T> {};
>
>The D&E described this rule, but as I recall, its example involved a
>derivation that looked like:
> template<typename T> struct B : T {};
>
>which is very different. I can understand the requirement to use
>this-> when deriving from T, but not A<T>.

A<T> isn't really much different from T, unless the template A has
already been specialized over type T. For example:

int foo();
template <typename T> struct A { int goo(); };


template <typename T> struct B: A

{ int bar() { return foo(); } };
template <> struct A <char> { int foo(); };

Which foo() should B<char>::bar() call? Global ::foo() or
A<char>::foo()? Put the specialization of A before the definition of B,
and it's clear that you should call A<char>::foo().

Jerry Coffin

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

In article <6bd2u9$4...@netlab.cs.rpi.edu>, luvm...@us.ibm.com says...

[ direct access to variables vs. get/set methods ]

> But what if in the future you change the attribute to be calculated or
> obtained from some database? Then, all the dozens or hundreds of
> places that directly access the member variable will have to be
> modified to use the getter method. Using getter methods all the
> time, hides the internal implementation and let's you change that
> internal implementation with no ripple effects to the rest of the
> code.

When/if you really run into this, you can avoid the problem quite
easily. Instead of using a member function, and converting all access
to the variable to use the member function instead, you simply turn
the member variable into a class of its own. Provide that class with
conversion operators to the original type, and voila' your code gets
executed as necessary. E.g.:

class whatever {
public:
int x;
// ...
};

turns into:

class X {
public:
operator int() {
// access database or whatever to determine value
return value;
}
X operator=(int new_value) {
// set value in database, or whatever...
}
};

class whatever {
public:
X x;
// ...
};

Now assignments to and from x use your code anyway, but avoid having
to make it clear in all other code that you're using code rather than
simply accessing a variable.

Keep in mind that a single class should generally be responsible for
only a single thing. If use of a particular member variable starts to
become more complex than simply assigning to it/using its value, it
most likely belongs in a class of its own.

I'm not sure I'd particularly recommend this technique for new code,
but if you have some existing code that allows public access to its
variables, it can make long-term maintenance much easier.

I should add that problems can arise with this basic design as well.
In particular, if you can no longer reasonably represent the TYPE of
thing being dealt with as the original type at all, then you have to
make more widespread changes. If there's ANY chance of this happening
at all, you're probably best off to start with the return being a
class or at least a typedef rather than making it a built-in type.
This will generally ease any long term transitions you have to make.

--
Later,
Jerry.

The Universe is a figment of its own imagination.

Bradd W. Szonye

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

>Bradd W. Szonye wrote:
>> The information that [a member data wart]

>> provides to me is that the variable is a private
>> member of the class. The more important benefit is that it provides
the
>> member names from clashing with names in the public interface, like
>> accessors and parameter names.

Alf P. Steinbach wrote in message <6bb6ak$m...@netlab.cs.rpi.edu>...


>Well, as I wrote originally, one should have as few rules as possible,
>but one absolute necessity is to distinguish between three non-
>overlapping sets of names: macros (all uppercase), functions (your
>convention here, I use initial caps), and everything else (your
>convention here, I use all lowercase with underscores).

Well, we mostly agree on this. My conventions are a bit different,
however:

Macros: all uppercase
Global/unique objects: initial uppercase
Functions: lowercase, trailing parentheses
Everything else: lowercase, no parentheses

Local: no scoping
Global/namespace: fully qualified scope
Public member: this->member or this->member()
Private member data: this->x_member
Private static member: ::type::x_Member
Pimple data: (this->)x_data->member

I'm not always consistent with my scoping conventions, although I'm
working to improve my habits. The only potential clash in the list above
is between an accessor name and the data member that it accesses.
(Another possible clash is between, say, class "color" and member
"color" of that type, but the scope operator resolves this.) I strongly
prefer not to "uppercase" functions or mangle the names of my data, so I
use a simple wart instead.

That's pretty much the difference between your style and mine: you
distinguish accessors from private data by lettercasing; I do it by
marking private data with a special wart. Overall, I don't find that
member warts decrease readability (contrast Hungarian notation), but I
find it useful to visually distinguish private members.

One other note: the member warts aren't necessary when I use pimpl data.
Since the pimpl class is an all-public struct, it uses the wartless
convention; since it's a different class, there are no clashes.

Is that enough of this holy war for now? Both our styles are consistent
and useful, with minimal intrusiveness; we each prefer our own solution;
there's only a problem if we attempt to mix our libraries in the same
project. <grin>

Bradd W. Szonye

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Herb Sutter wrote in message <6bb5fh$l...@netlab.cs.rpi.edu>...

>
>I wouldn't say that all experts insist on this, but I happen to feel
it's
>useful and so "trailing underscore for member names" is in our coding
>standards. When writing (and especially later reading) code, I often
find
>it helpful to be able to see easily whether "oh yeah, that's a member"
or
>not.

My personal problem with trailing underscores is this:

which_ of these words_ have_ a trailing_ underscore?
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Squint at those two lines, just like you do half-way through a grueling
day at the monitor, and easily tell which have the wart and which don't.
Depending on your newsreader font, it can be difficult to tell the
difference, so the wart is less effective visually. I coded under such a
standard once, and the underscore wart was occasionally a source of
hard-to-find bugs, because they look so similar to unadorned names.

it x_is much easier x_ to x_spot a bigger x_wart
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

>I must admit that none of us here really like m_ prefixes, though. But
you
>have to get used to them if you're doing MFC work... :-)

I kind of like the Xes myself. Mostly I just prefer the way that m_foo
or x_foo or foo_m stands out more than foo_ does.

Phlip

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

I use a meaning-based, not type-based, Hungarian Notation style. 'str'
for strings of any type, 'n' for numbers, 'clx' for collections, 'a'
for references, etc.

But I like type-based Hungarian Notation, and here's why. Suppose I'm
writing a program, and the notion comes over me to add some text in
italics to it. (I need that notion because, per my posts to
comp.object, I have no written specifications.)

Open the header files, search for "italic", and find 'lfItalic'. Now
HN is not magic enough to tell me how to use this thing, and I know
that under no circumstances should I invoke the on-line help for it.
So I type 'lfItalic' into DejaNews.

If it were just 'Italic', I would suffer hits from "alt.typography" to
"soc.culture.italy". But 'lfItalic' stands out in hundreds of posts
from newbies complaining about MS's online help systems. I can swiftly
locate example code that tells me to use it like this:

lf.lfItalic = TRUE;

That sort of obsessing is not just a corporate rule handed down from
the tier that can't code. The original meaning of HN related directly
to the need to make identifiers unique in an on-line help system.
(Particularily one not augmented by source-code browser databases.)

Return to the late 80's, warm up your 80286, boot OS/2 vs 1.x or DOS
with Windows strapped on, and start MSC 6.0 and its Programmers
WorkBench. If a member variable like 'lfItalic', or a structure
instance named 'lfMyUnselfDocumentingObject', confronts you, highlight
the 'lf' part, invoke the help, and get 'LOGFONT'.

The HN prefix itself was registered into the help index.

While you in the late 90's all cherish your freedom from compulsory
HN, try to imagine how - in a weak-type, weak-scope language like C -
you would write a multi-team, mega-line system integrated with its own
compiling tools and their on-line help files.

-- Phlip
======= http://users.deltanet.com/~tegan/home.html =======
-- What is the deal with Visual Basic Web pages and
exclamation points ?? --

Nathan Myers

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Alf P. Steinbach <al...@online.no> wrote:
>Well, as I wrote originally, one should have as few rules as possible,

But no fewer.

>but one absolute necessity is to distinguish between three non-
>overlapping sets of names: macros (all uppercase), functions (your
>convention here, I use initial caps), and everything else (your
>convention here, I use all lowercase with underscores).

Most of us have found no particular need to distinguish
function names from others; the "()" syntax suffices.
Distinguishing type names from everything else, however,
*is* necessary.

>Given this *single rule* -- which is a necessity -- your most
>important problem (benefit) disappears, and the code becomes
>more readable (or perhaps, just the single word readable) to boot.

In this area it takes a lot of experience to learn what works best.

While ignoring the experience of others may tickle your anarchism,
it won't result in better code. (I tickle my own anarchism in other
ways, such as working on free software.) Still, there is always
room in the world for more bad code, and while it's expensive to
write, it's cheap to throw away.

Phlip

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

HPS wrought:

>I must admit that none of us here really like m_ prefixes, though. But you
>have to get used to them if you're doing MFC work... :-)

I like them; they add a reality check:

g_ global
m_ member
s_ static
sm_ static member

And I would have thought of them myself if MS had not bent me over and
shoved them ... oops - we're moderated. :-)

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Stefan Rupp

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Good morning,

"Alf P. Steinbach" <al...@online.no> writes:
> Well, as I wrote originally, one should have as few rules as possible,

> but one absolute necessity is to distinguish between three non-
> overlapping sets of names: macros (all uppercase), functions (your
> convention here, I use initial caps), and everything else (your
> convention here, I use all lowercase with underscores).

To collect "everything else" into one class of names is IMHO too
simple. You propose to have macros lexicographistinct from other
names, but since macros should not be used at all in C++ (except
for include guards), this rule seems a bit obsolete. On the other
hand, you do not distingish between class data members, static data
members, local (automatic) variables, enumeration tags and type
names (did I forget something important?). There seems to be a
wrong focus here. I think the need to distinguish lexicographically
between those kinds of names is more important than to keep macros
distinguishable (although I follow the rule to use uppercase for
all preprocessor symbols, too).

Your "simple" rule may well apply to C sources, but C++ is much more
complicated and needs further refinement of your rule.

Ciao,
struppi

--
Dipl.-Inform. Stefan H. Rupp
Geodaetisches Institut der RWTH Aachen Email: str...@acm.org
Templergraben 55, D-52062 Aachen, Germany Tel.: +49 241 80-5295

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Kevin J. Hopps

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Alf P. Steinbach wrote:

[arguments against Hungarian notation]

> * The Hungarian notation prefixes are meta-information not subject to
> compiler checking, hence, relying on this information may/will lead to
> bugs (logical preconditions or postconditions should be expressed
> explitly, e.g. as assertions).

Just for fun, let me rewrite the above with a slight substitution:
COMMENTS are meta-information not subject to compiler checking,
hence, relying on this information may/will lead to bugs
(logical preconditions or postconditions should be expressed
explitly, e.g. as assertions).

> The last point may not be obvious, but one example I've encountered is,
> again, the "lpsz" or "sz" prefix, which implies a zero-terminated
> string, which is not necessarily what that char array contains. Cost
> me several hours to find that darned bug, all because of a misleading
> prefix (only present because the coding standard required it). Urgh.

The same could be said about comments. While you make a valid point, it
is not a convincing argument against either HN or comments. Requiring
either will not prevent people from writing bad code.
--
Kevin J. Hopps voice: 612.766.4740 kho...@adobe.com
Adobe Systems, Inc. internal: 3.4740 fax: 612.766.4750

David Abrahams

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Alf P. Steinbach wrote:
<snip>
> Vadim Zeitlin wrote:
><snip again>
> > Another one is that
> > it solves once and for all the problem of "SetX(int x) { m_x = x;
}".
>
> void SetX( int new_x_value ){ x = new_x_value; } // Or whatever...

A better example might have been:

Foo::Foo( A x, B y, C z )
: FooBase( x ), fY( y ), fZ( z )
{}

[I use the Taligent standard 'f' prefix for member names - 'm' probably
makes
more sense, but the 'f' sticks out visually better, and I'm used to it.
I
don't see any point in using an underscore - it's just more typing]

Somebody's going to get a wart here, unless you want to call the
parameters
'x_to_construct_with' or something, which seems like overkill and is
really
just a long wart. But the bottom
line is that you've gotta do what works for you, and my experience has
been
that my code is a lot more readable and maintainable when my member
variables
are prefixed. I generally don't go in for such things (certainly
Hungarian
notation seems to have a way of defeating the representational
abstraction
abilities of C++), but you can't argue with success... and member name
prefixes have made enough of a difference that everyone at my company
does it
by general consensus.

-Dave

Alf P. Steinbach

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

{This thread is getting a little heated... guys, please tune it
down and choose words more carefully. :-) -mod}

Nathan Myers wrote:
>
> Alf P. Steinbach <al...@online.no> wrote:

> >Well, as I wrote originally, one should have as few rules as
possible,
>

> But no fewer.

That I can agree with.


>
> >but one absolute necessity is to distinguish between three non-
> >overlapping sets of names: macros (all uppercase), functions (your
> >convention here, I use initial caps), and everything else (your
> >convention here, I use all lowercase with underscores).
>

> Most of us have found no particular need to distinguish
> function names from others; the "()" syntax suffices.

When you write "most of us", you're excluding everybody using
initial caps for functions. Fact is, the only place I've seen
functions without initial caps (except beginner's code) is the
C/C++ standard library, which follows the original C convention.
So, you're expressing some wishful thinking, but just that.

The "()" syntax is good and well when you're making a function
call. It doesn't help you when taking the address of a function
or passing functions around as data/parameters. And in
particular, C and C++ automatically translate a function name
sans "()" to a pointer, which in turn is a valid statement...

But the most convincing argument, for me, is that distinguishing
functions by initial caps makes it unnecessary to use all the
warts and whatever, which lower readability and thereby serve as
entry ports for hard to spot bugs.


> Distinguishing type names from everything else, however,
> *is* necessary.

Necessary, no, because the compiler will always catch a type
name being used as something else. Convenient and practical,
yes, because it's often natural to use the same name for an
instance of a type as for the type itself. But after nearly
20 years of programming, I still haven't settled on a single
best convention. Usually, I use the suffix "_type", which is
readable but sometimes seems to wordy.


> While ignoring the experience of others may tickle your anarchism,
> it won't result in better code. (I tickle my own anarchism in other
> ways, such as working on free software.) Still, there is always
> room in the world for more bad code, and while it's expensive to
> write, it's cheap to throw away.

Seems like you've run out of arguments... :-) What is your view
on conducting discussions by means of insinuations? (If you choose
to answer that question, please do so in [alt.flames], which I don't
read -- clc++m should not be used for mudthrowing contests.)

Hth.,


- Alf

Mark Wilden

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Bradd W. Szonye wrote in message <6b0k4m$6...@netlab.cs.rpi.edu>...
>> C(int height) : height(height) {}
>
>Is that last line a problem? I'm not sure.

No, it's fine, and I like it because I don't have to make up
artificial names either for members or constructor arguments.

>But there still is one other
>problem: I strongly prefer naming accessors the same as data members;
I
>only use "verbs" for procedures and mutators. (In other words, I hate
>"int C::getHeight() const;").
>
> int C::height() const;
>
>does not fit in well unless you name the corresponding actual data
>member something different.


I prefer to start functions with capitals, so that would fit your
preference neatly:

private:
int height;
public:
int Height() const { return height; }

Nathan Myers

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Doug Harrison <dHar...@worldnet.att.net> wrote:
>David Vandevoorde <dav...@cup.hp.com> wrote:
>
>>The `this->' convention also ensures that the designated
>>name ... will be looked up in dependent base classes and
>>not in namespace scopes.

A word to the wise:
The sentence above is *very important*. Reread it until you are
certain you understand it, because it affects most template code.

>That reminds me, is the Dec-96 draft's 14.6.2/4 [temp.dep] any
>different in the FDIS?

It's different, but not the way you hope.

>The former said that base classes aren't searched at definition

time for non-dependent names in derivations such as:
>
> template<typename T> struct B : A<T> {};
>

>... I can understand the requirement to use


>this-> when deriving from T, but not A<T>.

The problem is that the compiler doesn't know whether you will
specialize A<T>. A name could be in the base template, and not
in the specialization, or vice versa.

--

Mark Wilden

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Vadim Zeitlin wrote in message <6ba2qp$g...@netlab.cs.rpi.edu>...

>
> We all have to read sometimes (often) the code written by others.
>When you're reading an implementation of Foo::bar function how do
>you distinguish the Foo member variables from the global ones or
>even the local if the function is a bit long and uses a lot of
variables
>(ok, it's bad, but you've already seen 100 or 200 line functions,
>haven't you?)? This convention just makes the code easier to
>understand, that's all. Perhaps it's totally unimportant for you:
>than don't use it. But please do consider using it if you want
>the others to understand your code easier (and vice versa).


Wouldn't it be better to spend the effort convincing people to write
clear functions rather than applying bandaids like m_?

In good code, it's obvious what are members and what aren't (hint:
anything that's not a parameter or a local is a member). In bad code,
I've got a lot bigger problems understanding it than that! :)

Christopher Eltschka

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Julian Macri wrote:

[...]

> But what if in the future you change the attribute to be calculated or
> obtained from some database? Then, all the dozens or hundreds of
> places that directly access the member variable will have to be
> modified to use the getter method. Using getter methods all the
> time, hides the internal implementation and let's you change that
> internal implementation with no ripple effects to the rest of the
> code.

Are your classes that large that you access member variables at dozens
or hundreds of places? (That direct access from *outside* the class
should be avoided is IMHO a generally accepted rule).

Nathan Myers

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Michael Furman <en...@nospam.gssi.mv.com> wrote:
>
>I use similar rules (with some exceptions), but even this small

>set (IMO) is redundant and sometimes decrease redability:
>1. Good editor (IDE) could use different colors, styles for
> different names automatically.

This doesn't work.

C++ syntax (with its C inheritance) doesn't provide enough information
for an editor to identify where names come from, or even whether they
are types or variables. Anyway, how many of us print listings on a
color printer?

>2. Sometimes I don't want names to look differently, for example,
> function-style macros and functions!

You had better want them to look different. They have different
semantics, and if you forget which is which your code will break.

Nathan Myers

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Alf P. Steinbach <al...@online.no> wrote:
>> Most global names are not variables.
>
>Then they can't be confused with member variables. Good.
>Problem solved.

Glibness is a poor substitute for understanding, or experience.

>Better to wrap those C headers in a namespace, if that
>doesn't introduce name mangling (it shouldn't for extern C, but I
>may be wrong, if so, correct me -- there must be other solutions).

It's generally impossible to "wrap ... C headers in a namespace".
C headers routinely #include other headers, and in particular
the standard headers. To #include a standard header in another
namespace would be a grave error.

The projects where you can be certain you will never need to
use C headers describing some C library are far rarer even than
those that use no C libraries yet. (And are you really that
certain about what names come in with the standard C headers?)
If you're lucky, when you do need to use such a library you will
have source code and can translate it to C++ and clean up its
namespace usage. Wouldn't it be nice if we were lucky all the
time?

I still wonder why Mr. Steinbach (who says he detest unnecessary
rules) keeps a careful distinction between function names (which he
capitalizes) and variable names (which he doesn't). Nobody else
seems to need to create a separate namespace for functions; whereas,
since syntactically it's hard even for the compiler to tell a type
from a variable or function name, most of us are careful to
distinguish our type names.

Bottoms up,

Alf P. Steinbach

unread,
Feb 6, 1998, 3:00:00 AM2/6/98
to

Other people have pointed out the very same substitution, writing in
private mail. Evidently, it makes a good joke. So, I'll just copy &
paste my answer to a Microsoft employee:

I concede that you have a point, but comments are meant to be at
a *higher* level than the code, so the problem is not so severe.

In general, one good rule for comments is to not restate what's
already being said by the code, or more strongly, to not put as
a comment something that can be expressed in the language itself.

Except, of course, when time is running out and you have to get
that product out the door... ;-)


Cheers,

- Alf

Brock

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Bradd W. Szonye wrote in message <6bfaes$f...@netlab.cs.rpi.edu>...
<<

>
> which_ of these words_ have_ a trailing_ underscore?
> TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
>
<<
>

> it x_is much easier x_ to x_spot a bigger x_wart
> TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
<<

On the other hand, the first version is much easier to read.

Michael Furman

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Nathan Myers wrote:
> [...]

>
> Most of us have found no particular need to distinguish
> function names from others; the "()" syntax suffices.
> Distinguishing type names from everything else, however,
> *is* necessary.

Especially for embedded types like "int", "char" ...

Did you ever think that it is better to distinguish names by
color, font style (bold, italic, e.t.c) rather then by adding
redundant characters?

> >Given this *single rule* -- which is a necessity -- your most
> >important problem (benefit) disappears, and the code becomes
> >more readable (or perhaps, just the single word readable) to boot.
>
> In this area it takes a lot of experience to learn what works best.

Absolutely.

> [...]

--
---------------------------------------------------------------
== If you answer, please remove "nospam" from the address
Michael Furman, (603)893-1109
Geophysical Survey Systems, Inc. fax:(603)889-3984
13 Klein Drive engr @ gssi .
P.O. Box 97 mv . com
North Salem, 71543 . 1334 @
NH 03073-0097 compuserve.com
---------------------------------------------------------------

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Michael Furman

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Kevin J. Hopps wrote:
>
> Alf P. Steinbach wrote:
>
> [arguments against Hungarian notation]
>
> > * The Hungarian notation prefixes are meta-information not subject to
> > compiler checking, hence, relying on this information may/will lead to
> > bugs (logical preconditions or postconditions should be expressed
> > explitly, e.g. as assertions).
>
> Just for fun, let me rewrite the above with a slight substitution:
> COMMENTS are meta-information not subject to compiler checking,
> hence, relying on this information may/will lead to bugs
> (logical preconditions or postconditions should be expressed
> explitly, e.g. as assertions).
> [...]

Yes, but HN does not even pretend to carry any extra information about
the code, algorithm, use, e.t.c. - what is comments for.

Michael Furman

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Nathan Myers wrote:
>
> Michael Furman <en...@nospam.gssi.mv.com> wrote:
> >
> >I use similar rules (with some exceptions), but even this small
> >set (IMO) is redundant and sometimes decrease redability:
> >1. Good editor (IDE) could use different colors, styles for
> > different names automatically.
>
> This doesn't work.
Yes, it does. Though, alas, I don'n know such IDE that is available
now - except displaying keywords by different colors and automatic
indentation. (sometimes ago I participated in the development of some
"CASE" software with such capabilities).

> C++ syntax (with its C inheritance) doesn't provide enough information
> for an editor to identify where names come from, or even whether they
> are types or variables.

It should not be just an editor, but integrated part of system. And
of cause such information will be only "approximated" until code
compiles. But this is a different matter, and I am not sure that
it is appropriate for clc++m.

>Anyway, how many of us print listings on a
> color printer?

I've found recently that harder to by a B/W printer then a color one.
And sometimes ago I used the software ("Source Print"?) that printed
source text using bold font for keywords.

> >2. Sometimes I don't want names to look differently, for example,
> > function-style macros and functions!
>
> You had better want them to look different. They have different
> semantics, and if you forget which is which your code will break.

NO!
You would be correct in case if I didn't have anything more important
to think about - level ob abstractions, algorithms, domain, UI, e.t.c.

Using macros always is dangerous - you have design them very carefully
(IMO - the most important - tht incorrect/unsupported use cause syntax
error rather then incorrect behavior at the run time).

If I use function-stile macro (fore example - getchar() in many
implementation) - how often the knowledge that it is a macro
could help me?

Michael Furman

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Julian Macri wrote:
> [...]
>
> But what if in the future you change the attribute to be calculated or
> obtained from some database? Then, all the dozens or hundreds of
> places that directly access the member variable will have to be
> modified to use the getter method. Using getter methods all the
> time, hides the internal implementation and let's you change that
> internal implementation with no ripple effects to the rest of the
> code.

You don't have to change anything except the definition of attribute,
and internal implementation details will be hidden even better if you
will use "property" idiom.
See discussion about "properties" in this newsgroup.

Michael C. Grant

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Sorry, that's entirely too simplistic. It's possible to write clear code
with or without these so-called "bandaids." Some of us feel that these tools
make it _easier_ to write clear code.

Mark Wilden wrote in message <6bfr8t$m...@netlab.cs.rpi.edu>...


>Wouldn't it be better to spend the effort convincing people to write
>clear functions rather than applying bandaids like m_?
>
>In good code, it's obvious what are members and what aren't (hint:
>anything that's not a parameter or a local is a member). In bad code,
>I've got a lot bigger problems understanding it than that! :)

Daniel Karipides

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

For those out there that typically use first letter
capitalization for functions, what do you do about
the following.

class Vehicle
{
};

class Driver
{
Vehicle* vehicle; // what vehicle is the driver using?
public:
const Vehicle* Vehicle() const { return vehicle; } // oops, error
};

Clearly, that last line won't compile. What is the typical
style solution to this? I've been using:

class Driver
{
Vehicle* vehicle_m; // what vehicle is the driver using?
public:
const Vehicle* vehicle() const { return vehicle_m; }
};

But I'd love to get rid of the _m if someone has a better style.

-Dan
-----
kar...@mae.cornell.edu

Mark Wilden

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Alf P. Steinbach wrote in message <6bfnmd$l...@netlab.cs.rpi.edu>...

>Nathan Myers wrote:
>>
>> Alf P. Steinbach <al...@online.no> wrote:
>> >Well, as I wrote originally, one should have as few rules as
>possible,
>>
>> But no fewer.
>
>That I can agree with.

It's easy to agree with, since it's impossible to have fewer rules
than is possible. :)

Doug Harrison

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

On 6 Feb 1998 02:17:19 -0500, "Bradd W. Szonye"
<bra...@concentric.net> wrote:

>int foo();
>template <typename T> struct A { int goo(); };


>template <typename T> struct B: A

> { int bar() { return foo(); } };
>template <> struct A <char> { int foo(); };
>
>Which foo() should B<char>::bar() call? Global ::foo() or
>A<char>::foo()? Put the specialization of A before the definition of B,
>and it's clear that you should call A<char>::foo().

Thanks, I hadn't considered that case. I was under the impression that
one could derive B<T> from A<T> without having to worry about A<T>
specializations that could follow the definition of B<T>. Above,
suppose B<T> defined a function "void fun()", absent from A<T>, but
present in A<char> as "virtual void fun()". Does B<char>'s fun
override it?

--
Doug Harrison
dHar...@worldnet.att.net

Andrew Bell

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

On 6 Feb 1998 15:19:41 -0500, "Mark Wilden" <Ma...@mWilden.com> wrote:
>Wouldn't it be better to spend the effort convincing people to write
>clear functions rather than applying bandaids like m_?

1) m_ (or any extra character on a name) is easier to search for than
a commonly used word.

2) Some of us (many of us?) are working with million line programs
that have evolved over many years, been automatically translated from
Pascal, etc. Global variables are quite common. Converting this to
good style before doing any enhancements is not an option. Renaming
existing globals and using naming rules that help make new code more
readable under these circumstances is.

"Bad" code is often the code of the market leader.
Non-object-oriented code with bad variable names and poor structure
got Apollo to the moon, the shuttle in orbit, and built the internet.

3) Not everyone is a programming genius. It is a *lot* easier to get
competent but not expert programmers to use naming rules to make their
code more decipherable when you have to modify it, and then try to
teach them good design over the long haul. (Also, many of us are much
better programmers than teachers.)

Andrew Bell
abel...@mindspring.com

Bradd W. Szonye

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Alf P. Steinbach wrote in message <6bfnmd$l...@netlab.cs.rpi.edu>...
>
>When you write "most of us", you're excluding everybody using
>initial caps for functions. Fact is, the only place I've seen
>functions without initial caps (except beginner's code) is the
>C/C++ standard library, which follows the original C convention.
>So, you're expressing some wishful thinking, but just that.

Now you're only showing up your lack of experience. I've been involved
with projects that used:

verbNoun()
VerbNoun()
verb_noun()
vrb()
PRJ_VerbNoun()

... only half of which are capitalized. Often these rules are influenced
by platform or third-party-library names, or by experience with other
languages. For example, Windows programmers typically use VerbNoun() in
C++, while programmers who use Rogue Wave's tools.h++ often use
verbNoun(), after that library's convention, and those with a Unix C
background often use verb_noun(). I personally use verb_noun(), because
it mimics the style of the language itself and its library. If you're
going to support your Function() convention, stop calling the people who
disagree "beginners" and cite some usability studies not funded by
Microsoft (who prefer your style and might be biased).

Also, as has been pointed out, explain why you don't have a special
convention for type names! I personally don't, because the type names in
my code are fairly obvious from syntax, with the exception of functors
and other types which are intended to look like functions anyway. One of
the reasons it's easy to spot types is because I tend to prefix globals
with ::, and types are about the only globals I use.

Alf P. Steinbach

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Stefan Rupp wrote:
>
> Good morning,

Good Afternoon!


>
> "Alf P. Steinbach" <al...@online.no> writes:

> > Well, as I wrote originally, one should have as few rules as
possible,

> > but one absolute necessity is to distinguish between three non-
> > overlapping sets of names: macros (all uppercase), functions (your
> > convention here, I use initial caps), and everything else (your
> > convention here, I use all lowercase with underscores).
>

> To collect "everything else" into one class of names is IMHO too
> simple. You propose to have macros lexicographistinct from other
> names, but since macros should not be used at all in C++ (except
> for include guards), this rule seems a bit obsolete.

Macros are a fact of life. While I agree with your comment about
ideal usage, that isn't the reality one must face in daily
(or so) actual programming. Since the compiler can't check macro
usage and substitutions (they're performed before the compiler
proper), separating macro names is indeed useful and necessary, and
you're the first I've ever heard disagreeing somewhat with that.

> On the other hand, you do not distingish between class data members,

No need -- there's nothing to distinguish them from... :-)


> static data members, local (automatic) variables, enumeration tags

Again, no need.

> and type names

I mostly used suffix "_type", as a convenience and to improve
readability (by reducing necessity of creative variable naming).


>(did I forget something important?).

Yes, you forgot templates, which from a naming perspective have
the same role vis-a-vis concrete types as concrete types have
vis-a-vis variables. The best suggestion I can come up with
is a single underscore suffix, indicating "not quite complete",
or "must be specialized", but it doesn't feel 100% right. Since
the goal is to improve readability, introducing these pesky
warts seems like cutting the head off to cure a case of the flu.


> ...


> Your "simple" rule may well apply to C sources, but C++ is much more
> complicated and needs further refinement of your rule.

I think it's just the opposite. Since C++ has better typechecking,
and better facilities for abstraction, there's less need for the
programmer to do the compiler's work.

Cheers,


- Alf

Jason Smith

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Alf P. Steinbach wrote in message <6bed6a$b...@netlab.cs.rpi.edu>...
=Nathan Myers wrote:
=>
=> Alf P. Steinbach <al...@online.no> wrote:
=> >Nathan Myers wrote:
=> >> Member data names tend to have the same form as global names
=> >> coming from C headers.
=> >
=> >Ah, then we can put that q to rest. Simply don't use global
=> >variables, or, when you absolutely must, qualify the name.
=>
=> Most global names are not variables.
=
=Then they can't be confused with member variables. Good.
=Problem solved.

A large part of the problem is *addressed*, but the problem isn't solved
(the devil yet remains in the details). For example, consider the
standard
isxxx "functions" or errno -- often implemented as macros. In the case
of
the isxxx functions, they in fact hide global variables symbols. Also
consider that many (most?) compilers throw their own extensions into
those
headers as well. Unfortunately, namespaces can't make the problems with
macro skullduggery go away -- the damage has been done before namespaces
come into play.

=> "Shops" where no C headers are
=> used are scarce to nonexistent, and will be for a long time.
=
=(One such "shop" is the project I'm on right now. We use Java,
=C++ and Cobol. No C except standard/compiler C runtime lib.)

As mentioned previously, the "standard compiler/C runtime lib" is a case
in
point. Notwithstanding, as Nathan indicated, your project represents a
small fraction of the norm. Most projects will end up using C headers
because of dependencies on code that is exposed using a C interface:
legacy
code, engines implemented in C (to reach the widest possible audience),
or
dynamically loaded libraries implemented to be used across a plurality
of
compilers.

=Better to wrap those C headers in a namespace, if that
=doesn't introduce name mangling (it shouldn't for extern C, but I
=may be wrong, if so, correct me -- there must be other solutions).

The namespace won't mangle an extern "C" function name, but as a result,
it
doesn't completely distinguish the name either. An extern "C" symbol in
one
namespace identifies the same entity as another extern "C" symbol in
another
namespace. And again, what do we do with those symbols that are
actually
macros (ala errno)?

My own experience demonstrates that *some* namimg convention is
necessary,
at the least (and, IMO, *most*) to identify the symbol's scope
(apparently
the committee thought some naming rules were necessary too, considering
section 2.10.2).

Jason.

Alf P. Steinbach

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Nathan Myers wrote:
>
> Alf P. Steinbach <al...@online.no> wrote:
> >> Most global names are not variables.
> >
> >Then they can't be confused with member variables. Good.
> >Problem solved.
>
> Glibness is a poor substitute for understanding, or experience.
>

Do you feel better after that?


> >Better to wrap those C headers in a namespace, if that

> >doesn't introduce name mangling (it shouldn't for extern C, but I

> >may be wrong, if so, correct me -- there must be other solutions).
>

> It's generally impossible to "wrap ... C headers in a namespace".

Well, I weren't sure, -- I haven't been in situations where your
purported problem has been a problem -- but I just tried it out:


-------------------------------- wrap.cpp ---------------------------
// This written using VC++ 4.0, which is what I have on this machine.
// VC++ 4.0 doesn't have the new-fangled <iostream> header.
//
// Standard C headers don't have namespaces, so no problem with that.

#include <iostream.h>
#include <malloc.h> // free
#include "wrapper.h"


int main()
{
char const* hello_world;

hello_world = Wrapper::CHelloString();
cout << hello_world << endl;
free( const_cast<char*>( hello_world ) );

return 0;
} // main

--------------------------------- wrapper.h -------------------------
namespace Wrapper{
extern "C"
{

#include "hello.h" // Pure C header.

} // extern "C"
} // namespace Wrapper

--------------------------------- hello.h ---------------------------
extern char* CHelloString();

--------------------------------- hello.c ---------------------------
#include <string.h>

char* CHelloString()
{
return strdup( "Hello, Nathan!" );
} // CHelloString

----------------------------------------------------------------------


This compiles, links and runs. Although what works with the VC++
compiler is not always what the standard says, in this case I think
there's little disagreement between the compiler and the standard.

Now, I think that refutes your claim of "generally impossible".
But I'm not at all sure that this technique scales well. I think
it would be up to a person having such a problem to create a
solution. I'd be interested in hearing your thoughts on better
solutions, except the one of introducing warts as a C++ naming
convention. (Actually, I really don't see the problem... :-) )


> [snip]


>
> I still wonder why Mr. Steinbach (who says he detest unnecessary
> rules) keeps a careful distinction between function names (which he
> capitalizes) and variable names (which he doesn't).

Mainly because it keeps the code readable while avoiding the need
for most name ornamentation.


> Nobody else
> seems to need to create a separate namespace for functions;

Well, in the article <6bfr1a$m...@netlab.cs.rpi.edu> in this very
thread, right now, Mark Wilden says he uses this convention. I think
that refutes your claim of "nobody else". For that matter, all
Windows API functions use this style. And so on.


> whereas,
> since syntactically it's hard even for the compiler to tell a type
> from a variable or function name, most of us are careful to
> distinguish our type names.

You think you're *helping the compiler*???

Cheers,


- Alf

Mark Wilden

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Alf P. Steinbach wrote in message <6bfvs8$o...@netlab.cs.rpi.edu>...

>
>In general, one good rule for comments is to not restate what's
>already being said by the code, or more strongly, to not put as
>a comment something that can be expressed in the language itself.

I certainly disagree with that. I've found it very useful to write
code by writing the comments first, in an informal pseudocode, then
filling in the details with code, leaving the comments in. Since in
general it's easier to read English than C++, I or another reader can
get the gist of the function's implementation simply by reading the
comments.

Mark Wilden

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Michael C. Grant wrote in message <6bi6o7$2...@netlab.cs.rpi.edu>...

>Sorry, that's entirely too simplistic. It's possible to write clear
code
>with or without these so-called "bandaids." Some of us feel that
these tools
>make it _easier_ to write clear code.

My post was in reply to someone who said that things like m_ make bad
code easier to understand. I suppose it would, but that's not a
compelling reason for m_, since it's just a bandaid.

Mark Wilden

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Andrew Bell wrote in message <6bi8ks$4...@netlab.cs.rpi.edu>...

>
>1) m_ (or any extra character on a name) is easier to search for
than
>a commonly used word.

By that logic, we should add weird suffixes to everything. :) If you
rely on text-oriented searching, you're right. If you use more
sophisticated tools that understand C++, this doesn't apply.

>2) Some of us (many of us?) are working with million line programs
>that have evolved over many years, been automatically translated from
>Pascal, etc. Global variables are quite common. Converting this to
>good style before doing any enhancements is not an option. Renaming
>existing globals and using naming rules that help make new code more
>readable under these circumstances is.

Do you really rename existing globals under these circumstances?
Especially when, as you just pointed out, they are hard to search for?
And your second point simply asserts that using conventions makes code
more readable, which is what we're arguing about.


>"Bad" code is often the code of the market leader.
>Non-object-oriented code with bad variable names and poor structure
>got Apollo to the moon, the shuttle in orbit, and built the internet.

Sorry, I didn't mean to offend any bad coders. :)

>3) Not everyone is a programming genius. It is a *lot* easier to get
>competent but not expert programmers to use naming rules to make
their
>code more decipherable when you have to modify it, and then try to
>teach them good design over the long haul.

That's probably true. There are indeed some truly wretched programmers
who think using naming conventions automatically improves their code.
I avoid working with them.

Alf P. Steinbach

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Bradd W. Szonye wrote:
>
> Alf P. Steinbach wrote in message <6bfnmd$l...@netlab.cs.rpi.edu>...
> >
> >When you write "most of us", you're excluding everybody using
> >initial caps for functions. Fact is, the only place I've seen
> >functions without initial caps (except beginner's code) is the
> >C/C++ standard library, which follows the original C convention.
> >So, you're expressing some wishful thinking, but just that.

> Now you're only showing up your lack of experience. I've been involved
> with projects that used:

...


> going to support your Function() convention, stop calling the people who
> disagree "beginners"

I haven't done that. On the contrary, I'm very kind to people
calling me this and that (like, above you're calling me
inexperienced). Whatever you wish, sir.

> and cite some usability studies not funded by
> Microsoft (who prefer your style and might be biased).

Hm. I think you're writing this in affection.



> Also, as has been pointed out, explain why you don't have a special
> convention for type names!

As I've written several times in this thread, I usually use the
suffix "_type" for types. And I've given my reasons for doing
so. Perhaps you've done the same as many people do: read what
an opponent *implies* instead of what I've actually written.


> I personally don't, because the type names in
> my code are fairly obvious from syntax, with the exception of functors
> and other types which are intended to look like functions anyway. One of
> the reasons it's easy to spot types is because I tend to prefix globals
> with ::

That's a very good practice.


> and types are about the only globals I use.

That's also very good.


Best regards,


- Alf

Alf P. Steinbach

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Daniel Karipides wrote:
>
> For those out there that typically use first letter
> capitalization for functions, what do you do about
> the following.
>
> class Vehicle
> {
> };
>
> class Driver
> {
> Vehicle* vehicle; // what vehicle is the driver using?
> public:
> const Vehicle* Vehicle() const { return vehicle; } // oops, error
> };
>
> Clearly, that last line won't compile. What is the typical
> style solution to this? I've been using:
>
> class Driver
> {
> Vehicle* vehicle_m; // what vehicle is the driver using?
> public:
> const Vehicle* vehicle() const { return vehicle_m; }
> };
>
> But I'd love to get rid of the _m if someone has a better style.


I don't know if the following is *better*, because what's best
depends on the person and the context (including the team). But it
would be a way for you to get rid of the "_m":

class vehicle_type
{
public:
...
}; // vehicle_type


class driver_type
{
private:
vehicle_type* vehicle; // The vehicle the driver is using.

public:
...

vehicle_type const* Vehicle() const
{
return vehicle;
}
}; // driver_type

It's a bit more to type, but (in my experience) is faster to read,
and in the end probably saves typing. I would even go further and name
the function CurrentVehicle instead of just Vehicle. By not using
a short form, the meaning becomes clearer and there is less chance
of name collisions with later extensions/modifications (which may
have the same natural short form).

Hth.,

David Vandevoorde

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Doug Harrison wrote:
>
> On 6 Feb 1998 02:17:19 -0500, "Bradd W. Szonye"
> <bra...@concentric.net> wrote:
>
> >int foo();
> >template <typename T> struct A { int goo(); };
> >template <typename T> struct B: A
> > { int bar() { return foo(); } };
> >template <> struct A <char> { int foo(); };
> >
> >Which foo() should B<char>::bar() call? Global ::foo() or
> >A<char>::foo()? Put the specialization of A before the definition
> >of B, and it's clear that you should call A<char>::foo().
>
> Thanks, I hadn't considered that case. I was under the impression that
> one could derive B<T> from A<T> without having to worry about A<T>
> specializations that could follow the definition of B<T>. Above,
> suppose B<T> defined a function "void fun()", absent from A<T>, but
> present in A<char> as "virtual void fun()". Does B<char>'s fun
> override it?

It all depends on the ``points of instantiation for A<char>''
in your program. Let me digress in a somewhat simplified
discussion of ``point of instantiation'' ...

The ``point of instantiation'' (POI) concept is a very
important one. There are really two sorts of instantiations
to talk about:
(1) instantiation of things that eventually occupy
code or data memory; and
(2) instantiation of ``other things''.

(1) consists of:
(a) function and member function definitions (code),
(b) default function arguments (code),
(c) static data member definitions (data & possibly
initialization code).

(2) includes declarations (e.g., prototypes) and class
definitions.

Type (2) instantiations must be complete _before_ the point in
the source code where the instantiated entity is needed.
Specifically, the entity is ``injected'' in namespace scope.
For example:

template<class T> struct S { /* ... */ };

// <- POI of S<int>
void f() {
// <- not here because not namespace scope
S<int> s;
}
// Here would be too late

Clearly, if the (implicit) specialization S<int> were created
after the point where it is needed in the definition of f(),
it would come too late. I.e., we cannot ``back-patch'' the
definition of f() to use the definition of S<int> that follows
it.

Type (1) instantiations are completed _after_ the point in the
source where the enitity is needed -- again in namespace scope.
Example:

template<class T>
void f(T) {
// ...
}

// <- POI of the _declaration_ of f<int>(int)
void g() {
f(42);
}
// <- POI of the _definition_ (body) of f<int>(int)

Why this requirement? Because of the possible need to
instantiate a template function that calls the function
creating the point of instantiation:

template<class T>
void f(T a) {
// ...
g(a); // g dependent name
// ... -> not looked up until instantiation
};

// <- (*)
void g(int) {
f(8);
}

If the body of f<int>(int) were created (instantiated)
at point (*), there is a good chance that an error would
occur because g(int) is not yet visible at that point
(assuming there was no prior declaration of g(int)).

Also note that the instantiation of a specialization of
a class template creates POIs for the definition of each
virtual function member of that class template.

Finally, POIs are also created by explicit instantiation
directives such as:

template struct S<double>; <- POI for S<double>

Now back to whether specializations override or not
(your question above). They do, but for that mechanism
to work correctly, the specialization _must_ appear
before any POI of that specialization. This prompts I
believe the following rule-of-thumb:

! (1) A partial specialization should appear as soon as
! possible after its primary template. It should be
! placed in the same file (or a mechanism should be
! used to prevent separate inclusion of both elements).
!
! (2) An explicit specialization should either follow
! (1) above, or appear as soon as possible after a
! declaration of a type that is a template-argument
! for that specialization.

In both cases I'm talking about the _declaration_ of
the specialization. The idea of this rules is to prevent
inadvertent creation of POIs between primary templates
and user-defined specializations. Rule (2) above enables
the ``traits'' technique, I believe.

(please correct me if you see a problem with the above.)

You'd also want a similar characterization for overloaded
function templates, but that is a bit harder because those
things don't have the concept of a ``primary template''.

And then, perhaps the hardest part of using templates:
there can be (and often are) multiple POIs for a single
specialization in a program.

! Every POI of a given (implicit) specialization must result
! in indentical bindings.

A violation of that rule is a violation of the ODR (one-
definition rule) which compilers are not always required
to diagnose (and it is difficult to diagnose them in general).

E.g.,

// hdr.h:
template<typename T>
void f(T a) {
g(a); // Dependent name
}


// file_1.C:
#include "hdr.h"

void g(double);

void p1() { f(0); } // indirectly calls g(double) !!

// <- POI for f<int>(int)

// file_2.C:
#include "hdr.h"

void g(int);
void g(double);

void p2() { f(0); } // indirectly calls g(int) !!
// <- POI for f<int>(int)

Since the call `g(a)' binds differently for the two POIs
of `f<int>(int)' the program above has undefined behavior.
This sort of argues against most forms of implicit
conversions and for some kind of ``atomicity'' in the
declaration of overloaded function sets.

I suppose the stuff I just wrote may appear a little
daunting at first, but most of the ideas make sense I think.
So after playing with them for a short while they shouldn't
be too hard to remember. Not being burned by their implications
may be tougher in large projects.

Daveed

Alf P. Steinbach

unread,
Feb 7, 1998, 3:00:00 AM2/7/98
to

Mark Wilden wrote:
>
> Alf P. Steinbach wrote in message <6bfvs8$o...@netlab.cs.rpi.edu>...
> >
> >In general, one good rule for comments is to not restate what's
> >already being said by the code, or more strongly, to not put as
> >a comment something that can be expressed in the language itself.
>
> I certainly disagree with that. I've found it very useful to write
> code by writing the comments first, in an informal pseudocode, then
> filling in the details with code, leaving the comments in. Since in
> general it's easier to read English than C++, I or another reader can
> get the gist of the function's implementation simply by reading the
> comments.

I think we're really in agreement. You don't write and then keep
comments like "decrement x", do you? (Of course not.) Such a
comment would be at the level of the code. When you're writing
pseudocode, you're presumably writing things at a much higher
level than the eventual real code, capturing small chunks of
code by each comment. In some cases, but not all, a comment
will eventually be completely replaced by a function call.

Agree?


- Alf (not really sure whether this topic belongs in clc++m,
follow-ups set to [comp.programming])

Nathan Myers

unread,
Feb 8, 1998, 3:00:00 AM2/8/98
to

{ This thread has degenerated into ``polite insults''.
Please desist. -vdv }


Alf P. Steinbach<al...@online.no> wrote:
>Nathan Myers wrote:
>> Glibness is a poor substitute for understanding, or experience.
>
>Do you feel better after that?

Mr. Steinbach repeatedly misses the point. Good engineering practice
comes from experience, not from high-school debating skills, not from
clever logic-chopping, and not from counting noses. Cleverness provides
ideas to try, but only experimentation and long experience can sort out
the good ideas from the rest.

>> >Better to wrap those C headers in a namespace, if that
>> >doesn't introduce name mangling (it shouldn't for extern C, but I
>> >may be wrong, if so, correct me -- there must be other solutions).
>>
>> It's generally impossible to "wrap ... C headers in a namespace".
>

>Well, I wasn't sure, -- I haven't been in situations where your


>purported problem has been a problem -- but I just tried it out:

>... [extended, pointless example elided] ...

>Now, I think that refutes your claim of "generally impossible".

It's easy to contrive examples that avoid problems, and illustrate
nothing. As I said in the original posting, and which Mr. Steinbach
failed to quote or illustrate, C headers routinely include other headers.
Wrapping a header which ultimately includes a standard header (or
might in some later version come to include a standard header) would
be a grave error.

>But I'm not at all sure that this technique scales well. I think


>it would be up to a person having such a problem to create a
>solution. I'd be interested in hearing your thoughts on better
>solutions, except the one of introducing warts as a C++ naming
>convention. (Actually, I really don't see the problem... :-) )

Being unable to see problems until after they bite is not a virtue.

>> I still wonder why Mr. Steinbach (who says he detest unnecessary
>> rules) keeps a careful distinction between function names (which he
>> capitalizes) and variable names (which he doesn't).
>
>Mainly because it keeps the code readable while avoiding the need
>for most name ornamentation.

This does not answer the question. An unnecessary and unjustified
distinction is being made. Why? Did you just copy it without
understanding why or why not?

>> whereas,
>> since syntactically it's hard even for the compiler to tell a type
>> from a variable or function name, most of us are careful to
>> distinguish our type names.
>
>You think you're *helping the compiler*???

No, I am helping readers of my code. If it's hard for a compiler
to distinguish types from other names, people will have worse
trouble without some visual aid.

Alf, do what you like, I don't care. Chances are epsilon to zero
that I will ever see your code, but many people read mine.

I have done the work of experimenting, over many years, to discover
what helps make C++ code understandable. The convention I use is not
the only one that works, but I find it infinitely preferable to one
that doesn't work. Wasting a key visual distinction (capitalization)
on something that makes no difference (variable vs. function) while
failing to distinguish something that makes a key difference (types
vs. other names) is a fundamental error.

Nathan Myers

unread,
Feb 8, 1998, 3:00:00 AM2/8/98
to

Mark Wilden<Ma...@mWilden.com> wrote:
>Alf P. Steinbach wrote in message <6bfvs8$o...@netlab.cs.rpi.edu>...
>>In general, one good rule for comments is to not restate what's
>>already being said by the code, or more strongly, to not put as
>>a comment something that can be expressed in the language itself.
>
>I certainly disagree with that. I've found it very useful to write
>code by writing the comments first, in an informal pseudocode, then
>filling in the details with code, leaving the comments in.

Alf is dead right, here. It has been repeatedly demonstrated that
comments which repeat code come, over (a remarkably short) time, to
contradict the code.

--

Phlip

unread,
Feb 8, 1998, 3:00:00 AM2/8/98
to

Mark Wilden wrote:

>...I've found it very useful to write


>code by writing the comments first, in an informal pseudocode, then

>filling in the details with code, leaving the comments in...


This advice should be graven in white marble, towed behind Piper Cubs,
and drilled into students:

Write the comments first.

If the comments are not in your brain yet, where is the code going to
come from?

(And this parallels a crucial management practice: Draft the user
manual first!)

-- Phlip

Mark Wilden

unread,
Feb 9, 1998, 3:00:00 AM2/9/98
to

Nathan Myers wrote in message <6bjjb8$b...@netlab.cs.rpi.edu>...
>>
>>I certainly disagree with that. I've found it very useful to write

>>code by writing the comments first, in an informal pseudocode, then
>>filling in the details with code, leaving the comments in.
>
>Alf is dead right, here. It has been repeatedly demonstrated that
>comments which repeat code come, over (a remarkably short) time, to
>contradict the code.

Well, it's also been repeatedly stated by software engineering gurus
that
writing the comments first, then filling in the code is an excellent way
to
program, so I think I'll stick with it. :)

If one doesn't update one's comments as the code changes, one is simply
displaying bad programming skills. Just because some misuse a technique,
that's
no reason for the rest of us to abandon it, if it has merit on other
bases.

And after all, any comment that describes what a function does "repeats
code."
Are we to abandon those?

Stefan Rupp

unread,
Feb 9, 1998, 3:00:00 AM2/9/98
to

Good morning (again) :),

"Alf P. Steinbach" <al...@online.no> writes:
> > To collect "everything else" into one class of names is IMHO too
> > simple. You propose to have macros lexicographistinct from other
> > names, but since macros should not be used at all in C++ (except
> > for include guards), this rule seems a bit obsolete.
>
> Macros are a fact of life. While I agree with your comment about
> ideal usage, that isn't the reality one must face in daily
> (or so) actual programming. Since the compiler can't check macro
> usage and substitutions (they're performed before the compiler
> proper), separating macro names is indeed useful and necessary, and

OK, "real existing" software usually make use of preprocessor macros,
but one can't state that fact and deny the use of global names on the
other hand. Those are used, too.

> you're the first I've ever heard disagreeing somewhat with that.

No, you misinterpreted my comment. I do think that macro names should
be distinguishable from other names, but to narrow the number of classes
of identifiers to three (macros, functions and "the rest") is the thing
I am sceptic about.

> > On the other hand, you do not distingish between class data members,
>
> No need -- there's nothing to distinguish them from... :-)
>
> > static data members, local (automatic) variables, enumeration tags
>
> Again, no need.

Well, I do believe that it is desirable to distinguish between those
identifiers. For example in the statement:

come_valiable = SomeClass::SomeName;

Is this name "SomeName" an enumeration tag or a static data member
or a constant defined in that class scope? One should be able to
get information about this without actually looking at the class
definition frame of class SomeClass. With proper conventions
regarding identifier naming this information is immediately present.

> >(did I forget something important?).
>
> Yes, you forgot templates, which from a naming perspective have
> the same role vis-a-vis concrete types as concrete types have
> vis-a-vis variables. The best suggestion I can come up with
> is a single underscore suffix, indicating "not quite complete",
> or "must be specialized", but it doesn't feel 100% right. Since
> the goal is to improve readability, introducing these pesky
> warts seems like cutting the head off to cure a case of the flu.

:) I hate templates!

> > Your "simple" rule may well apply to C sources, but C++ is much more
> > complicated and needs further refinement of your rule.
>
> I think it's just the opposite. Since C++ has better typechecking,
> and better facilities for abstraction, there's less need for the
> programmer to do the compiler's work.

This isn't about making it easier for the compiler but making code
more readable for the programmer (and maintainer). I WANT to know
if some identifier designates a static class member or a constant,
so my naming convention should be able to distinguish between those
kinds of names.

Ciao,
struppi

--
Dipl.-Inform. Stefan H. Rupp
Geodaetisches Institut der RWTH Aachen Email: str...@acm.org
Templergraben 55, D-52062 Aachen, Germany Tel.: +49 241 80-5295

Tim Ottinger

unread,
Feb 9, 1998, 3:00:00 AM2/9/98
to


Brock wrote:

> Bradd W. Szonye wrote in message <6bfaes$f...@netlab.cs.rpi.edu>...
> > which_ of these words_ have_ a trailing_ underscore?
> > TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
> >
> > it x_is much easier x_ to x_spot a bigger x_wart
> > TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
> <<
>
> On the other hand, the first version is much easier to read.

Agreed here. The bigger warts are like "speed bumps" which prevent me from scanning or doing quick read of the code. I have to slow down and eliminate the warts in order to get the sense of the sentence. I also have read it three times, and each time my
eyes got so far in and then backed up, like they are trying to pull the context themselves. In the first case, I scanned it quickly and got meaning out of it easily, and was more able to ignore the warts. If I was really needing to know what kind of thing
"trailing" was, the little wart was there for me. The second was more painful. I would think that reading through a few hundred lines of that code would just about hurt me. I'd be ready for a nap or a long walk before continuing.

Personal opinions, of course, but I wonder if they're not pretty common. Big warts are made to prevent quick scans. Is this an admirable goal? How often?

Tim Ottinger

unread,
Feb 10, 1998, 3:00:00 AM2/10/98
to


Mark Wilden wrote:

> Nathan Myers wrote in message <6bjjb8$b...@netlab.cs.rpi.edu>...

> >Alf is dead right, here. It has been repeatedly demonstrated that
> >comments which repeat code come, over (a remarkably short) time, to
> >contradict the code.
>
> Well, it's also been repeatedly stated by software engineering gurus
> that writing the comments first, then filling in the code is an excellent
> way
> to program, so I think I'll stick with it. :)

I was peripherally involved with an Ada project back in the late '80s.
It was quite a curiosity because the coding standards forbade comments.
Before you panic, realize I'm neither condoning nor condemning this,
just stating a fact from the past. That said...

The amazing thing is that they were not an uncontrolled hackers'
project. It was done under rigorous controls and with lots of
inspections and incredibly close managment, etc. The people
were good developers and were "bought in" to the product.

Now, that's all setup for the main point: it wasn't so bad. The
code was not an undecypherable morass. They had inspections,
as I said. If the code (undocumented) was not easily readable
and understandable by the reviewers (always talented and
skilled developers) then it was rejected. They were true sticklers
for meaningful names and clear design. It's kind of the "make
it hard on yourself so that you get used to more rigor", in that
they did make it harder on themselves sometimes, but the
project worked, was maintainable, and the managers liked to
do what was called "stirring the contractors" so new people
inherited the code usually within a few months of the time it
was written. They did fine.

There are plenty of ways that "the code is the documentation"
won't suffice, but you can go quite a long way by simply making
the code make sense.

Ian Knowles

unread,
Feb 10, 1998, 3:00:00 AM2/10/98
to

"Mark Wilden" <Ma...@mWilden.com> wrote:

> Since in
>general it's easier to read English than C++, I or another reader can
>get the gist of the function's implementation simply by reading the
>comments.

In large development environments with many programmers (usually with
different attitudes and styles to writing comments and quite possibly
with English as a second language) such comments will often tend to be
either badly re-worded over time or (worse yet) simply left alone
while the code around them is re-worked.

I have found that this can make such comments actually more of a
hinderance than any useful guideline because programmers (and
especially inexperienced ones) will often assume that the code is
"supposed" to be in accordance with such comments.

Such assumptions can often lead to much wasted effort in holding an
illogical "interpretation" of how the C++ code must be achieving the
"supposed" documented behaviour before accepting that the comment is
innaccurate or possibly even just plain wrong.

I realise that it may also take many hours to understand the actual
C++ code, however, I don't think that time invested in reading and
understanding the actual C++ code will be time badly wasted
(espeically for inexperienced programmer's).


Regards,

Ian Knowles (remove the .nospam to reply)

Christopher Eltschka

unread,
Feb 10, 1998, 3:00:00 AM2/10/98
to

Mark Wilden wrote:
>
> Andrew Bell wrote in message <6bi8ks$4...@netlab.cs.rpi.edu>...
> >
> >1) m_ (or any extra character on a name) is easier to search for
> than
> >a commonly used word.
>
> By that logic, we should add weird suffixes to everything. :) If you
> rely on text-oriented searching, you're right. If you use more
> sophisticated tools that understand C++, this doesn't apply.
>
> >2) Some of us (many of us?) are working with million line programs
> >that have evolved over many years, been automatically translated from
> >Pascal, etc. Global variables are quite common. Converting this to
> >good style before doing any enhancements is not an option. Renaming
> >existing globals and using naming rules that help make new code more
> >readable under these circumstances is.
>
> Do you really rename existing globals under these circumstances?
> Especially when, as you just pointed out, they are hard to search for?
> And your second point simply asserts that using conventions makes code
> more readable, which is what we're arguing about.
>

Well, maybe his tools do it automatically for him. The tools
must change some names globally anyway - imagine a pascal program
containing s.th. like

type
contract_state = (signed, unsigned); { is the contract already signed?
}

var
int: integer;

Now, if the tool is capable of changing such names consistently
in the complete code, enforcing a simple naming convention
(be it scope prefix, type based hungarian notation, or simple
capitalisation rules) should not be too complicated to add, I guess.

[...]

Tim Ottinger

unread,
Feb 10, 1998, 3:00:00 AM2/10/98
to


Andrew Bell wrote:

> 1) m_ (or any extra character on a name) is easier to search for than
> a commonly used word.

Would you search for any member of any class? Or do you look forsomething
meaningful? In a large system, with a great many classes
and member variables, m_ should be almost as common as "if" and
"for". Is that good? Probably m_HomeAddress is less common,
but so would be homeAddress in this case. And would you really
not know a member variable name or its containing class and look
for the m_? I think this may not be the most valid of arguments..

> 2) Some of us (many of us?) are working with million line programs
> that have evolved over many years, been automatically translated from
> Pascal, etc. Global variables are quite common. Converting this to
> good style before doing any enhancements is not an option. Renaming
> existing globals and using naming rules that help make new code more
> readable under these circumstances is.

I think that we have to be practical, and that definitely means
makingthings clear. I think changing poor variable, class, and object
names to
good ones is a good way to start. But nobody said that you couldn't
rename variables. The discussion, I think, is about what you rename
them _to_. Another problem is finding out what names are already
taken...

> "Bad" code is often the code of the market leader.
> Non-object-oriented code with bad variable names and poor structure
> got Apollo to the moon, the shuttle in orbit, and built the internet.

Do you think this is really true? I wonder if the structure was reallypoor
and the variable names were really ill conceived. I know plenty
of gov't programmers who are quite capable and who build quite
acceptable code in these respects. I've not seen the original code
for any of these projects. I would not be surprized if some of these
systems were done in C or PLM or something, but that's not
to say they were done badly.

> 3) Not everyone is a programming genius. It is a *lot* easier to get
> competent but not expert programmers to use naming rules to make their
> code more decipherable when you have to modify it, and then try to

> teach them good design over the long haul. (Also, many of us are much
> better programmers than teachers.)

Naming rules are good. It's warts the other poster seemed to argue
against.

Besides, if you have naming rules, you have to review products to see if
the naming rules
are followed. Strangely enough, review is the best way to teach people to
write readable code, too. I think that good design is clearly not going
to be learned if it isn't examined by the student/practitioner

But I think that it sounds as if you are arguing for naming standards
in general rather than a particular naming standard here. Again, I'm
trying to take a reasonable stance in all of this, and I understand that
sometimes "a programmer has got to do what a programmer has got
to do", but I didn't hear any solid arguments in favor of a particular
naming standard that requires m_* or *_ or G* or K*, or psz and
the like.

Tim

John McClean

unread,
Feb 10, 1998, 3:00:00 AM2/10/98
to

> Daniel Karipides wrote:
> >
> > For those out there that typically use first letter
> > capitalization for functions, what do you do about
> > the following.
> >
> > class Vehicle
> > {
> > };
> >
> > class Driver
> > {
> > Vehicle* vehicle; // what vehicle is the driver using?
> > public:
> > const Vehicle* Vehicle() const { return vehicle; } // oops, error
> > };
> >
> > Clearly, that last line won't compile. What is the typical
> > style solution to this? I've been using:
> >
> > class Driver
> > {
> > Vehicle* vehicle_m; // what vehicle is the driver using?
> > public:
> > const Vehicle* vehicle() const { return vehicle_m; }
> > };
> >
> > But I'd love to get rid of the _m if someone has a better style.
>

I like:

const Vehicle * getVehicle const { return vehicle; }

'setX', 'getX', and 'isX' may be dull, but used consistently (like
anything else) they make life a lot easier. Plus they get around
most of the problems like the above.

John McClean

Nathan Myers

unread,
Feb 10, 1998, 3:00:00 AM2/10/98
to

Mark Wilden<Ma...@mWilden.com> wrote:
>Nathan Myers wrote ...

>>It has been repeatedly demonstrated that
>>comments which repeat code come, over (a remarkably short) time, to
>>contradict the code.
>
>Well, it's also been repeatedly stated by software engineering gurus
>that writing the comments first, then filling in the code is an
>excellent way to program, so I think I'll stick with it. :)

It's a good way to begin programming. Construction engineers
use scaffolding. They take down the scaffolding when they're
finished, because it's in the way.

>If one doesn't update one's comments as the code changes, one is simply
>displaying bad programming skills. Just because some misuse a technique,
>that's no reason for the rest of us to abandon it, if it has merit on
>other bases.

A comment that duplicates code is a distraction. A comment that
contradicts code is pernicious. Maintainers in a hurry don't look
around for comments to fix up, they have plenty else to do. That
you disapprove of their behavior doesn't change it, and doesn't
change the maintainability of your code.

If that maintainability depends on huge numbers of comments being
maintained in parallel, your code will rot very quickly indeed.

>And after all, any comment that describes what a function does "repeats
>code." Are we to abandon those?

*Especially* those. Comments should describe purpose, not action.
Page 138 of "The C++ Programming Language, Third Edition" by
Stroustrup is apropos, here. If you don't have the book yet,
you know what to do.

Bradd W. Szonye

unread,
Feb 11, 1998, 3:00:00 AM2/11/98
to

You're right about "big warts" being less readable, and it's one of the
arguments I use against Hungarian Notation in general. They simply
aren't acceptable in commonly-used names.

I reserve the use of "big warts" for names that should be highlighted as
unusual or special. It's these cases where I think that an unobtrusive
wart is detrimental; it's too easy to overlook the single-underscore
wart, especially when there's a similar, unadorned name in the same
scope:

Is it obvious that wart and wart_ are different?
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

versus:

Is it ovbious that wart and x_wart are different?
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

One of the cases where I feel it's useful to highlight a "special" use
of a name is when that name is part of a module's "private interface."
Using a wart there serves two purposes: it keeps the private parts of a
module from clashing with public names, and it highlights the use of
private names.

The latter is important for reasons I've stated elsewhere; the former is
useful both because it makes the difference between, say, parameters and
member data obvious, and it makes the use of "internal details" more
apparent for use in, say, code reviews.

If you've got a style convention that says, "Prefer use of accessor
methods to direct data access even in class methods," (which is not at
all unusual), then a wart helps both visual and automated scanning of
the code for all uses of direct access to private parts. In preparing
for a code review, I can grep something like "\bx_" (find "x_" at
beginning of word) to see all uses of private stuff and verify that
they're acceptable exceptions to the rule.

Hopefully this makes clear why I prefer the "x_" wart for names in the
private interface: it meets my naming goals of (1) highlighting the use
of internal names, (2) separating the namespaces of internal and public
names, and (3) making the distinguishing mark (wart) visually obvious.

Again, I agree with your principles of making public names as readable
as possible. It's only for private names that I recommend warts. Also,
your design goals for a naming convention may differ from mine, making
this use of warts unnecessary or undesirable.
--

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Bradd W. Szonye

unread,
Feb 11, 1998, 3:00:00 AM2/11/98
to

John McClean wrote:
>
> I like:
>
> const Vehicle * getVehicle const { return vehicle; }
>
> 'setX', 'getX', and 'isX' may be dull, but used consistently (like
> anything else) they make life a lot easier. Plus they get around
> most of the problems like the above.

The trouble with names like "getAttribute" is that people tend to
associate names that start with a verb to "do stuff" rather than simply
access a (possibly derived) attribute. For this reason, I prefer simpler
names like "attribute()" for accessors, especially since they are so
commonly used. Some people (like me) might even argue that you're moving
the "wart" from the private interface (m_*) to the public interface
(get*). I agree that warts are a bad thing in general, but that they are
useful to distinguish internal details.

To answer the original question, I use the scope operator to distinguish
the name of a global type from a same-named attribute:

::attribute type::attribute() const { return x_attribute; }

This is useful for many types which are also useful as attribute names,
like "color" and "port." There are three parts to this: the global type
is explicitly scoped (::attribute), the accessor uses the same name
(attribute()), and the internal data is highlighted and de-clashed with
a wart (x_attribute). Further qualifying the internal date with the
"this->" prefix isn't a bad idea either, as explained in other articles.

Unfortunately, this usage doesn't completely remove the use of warts;
however, if you absolutely detest warts, there are other solutions, like
capitalization standards. Those that prefer capitalizing type names and
function names may find this preferable:

::Attribute Type::Attribute() const { return attribute; }

This doesn't meet my own goal of highlighting use of internal data, but
not everyone thinks that it's a big enough advantage to justify the loss
of readability inherent in warts. It does meet the criterion of avoiding
all warts, so long as you don't consider capitalization a wart. (I do
consider it a wart of sorts, since it differs from the natural usage in
the language I write identifiers in, English.)

Finally, if you think that "::Attribute" is ugly, you can follow the
practice from the standard library and use one of

typedef ::attribute attribute_type;
typedef ::Attribute AttributeType;

in your class definition.

Rob Stewart

unread,
Feb 11, 1998, 3:00:00 AM2/11/98
to

This is a multi-part message in MIME format.
--------------CB47FFECC4DF56E862F613E8
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Tim Ottinger wrote:

> Brock wrote:
>
> > Bradd W. Szonye wrote in message <6bfaes$f...@netlab.cs.rpi.edu>...
> > > which_ of these words_ have_ a trailing_ underscore?
> > >

> > > it x_is much easier x_ to x_spot a bigger x_wart
> >

> > On the other hand, the first version is much easier to read.
>
> Agreed here. The bigger warts are like "speed bumps" which prevent me from scanning or doing quick read of the code. I have to slow down and eliminate the warts in order to get the sense of the sentence. I also have read it three times, and each time my
> eyes got so far in and then backed up, like they are trying to pull the context themselves. In the first case, I scanned it quickly and got meaning out of it easily, and was more able to ignore the warts. If I was really needing to know what kind of thing
> "trailing" was, the little wart was there for me. The second was more painful. I would think that reading through a few hundred lines of that code would just about hurt me. I'd be ready for a nap or a long walk before continuing.
>
> Personal opinions, of course, but I wonder if they're not pretty common. Big warts are made to prevent quick scans. Is this an admirable goal? How often?

Tell me now, was the following easy to read when you first saw it (ignoring any naming convention differences of opinion)?

Fubar & Fubar::operator =(
Fubar const & i_RHS)
{
if (&i_RHS != this)
{
// do some assignment work
}
return *this;
}

I doubt that it was clear and easy to read when you first saw code like the above. For that matter, was a sentence like this easy to read when you first were learning English? Not likely.

Despite the initial effort to learn to read something, much good can often come from various encoding conventions. English is awkward to one who reads French and is learning English (that it is awkward for English speakers is another matter!). C/C++ is
awkward
for Pascal programmers and vice versa. Does this mean that these languages aren't valuable or worth using? No. It means you're not used to them.

With time, you can grow accustomed to any notation. Some will allow greater efficiency in the beginning. Some will be more expressive. Some may even meet both goals. The key is to look past initial discomfort to see if there is a tangible and beneficial
result
from using a particular notation. If the benefit doesn't outweigh the discomfort, don't use the notation. If it does, use the notation. It's that simple.

As to the specific discussion, I prefix dms with "m_," static dms with "s_," formal parameters with "i_," "o_," or "io_," and non-member statics (globals) with "g_." I have found the additional information they convey to be valuable. You may not.

--
Robert Stewart | r...@giage.com
Software Engineer | using std::disclaimer;
Giage, Ltd.


--------------CB47FFECC4DF56E862F613E8
Content-Type: text/x-vcard; charset=us-ascii; name="vcard.vcf"
Content-Transfer-Encoding: 7bit
Content-Description: Card for Robert Stewart
Content-Disposition: attachment; filename="vcard.vcf"

begin: vcard
fn: Robert Stewart
n: Stewart;Robert
org: Giage, Ltd.
adr: 214 E 9TH ST, FL 4;;;CINCINNATI;OH;45202-2108;USA
email;internet: donot...@giage.com
title: Software Engineer
tel;work: (513)562-8700x224
x-mozilla-cpt: ;0
x-mozilla-html: TRUE
version: 2.1
end: vcard


--------------CB47FFECC4DF56E862F613E8--

Shawn Tooley

unread,
Feb 11, 1998, 3:00:00 AM2/11/98
to

I know I am out of my league; I am a Junior in the CS program at Univ. Of
Akron in Ohio. In school, I have had different professors request your
comments are supposed to be in this form and your code has to be like
this.... Is there any written standards on how your code should look. For
example: where to put brackets; how many spaces between lines and such.
During compile I know it does not make a difference; just wanting to prepare
myself for the real world... Thanks...

--
Shawn Tooley
sh...@ip-inc.com
My ICQ Web-Page Address Is:
http://wwp.mirabilis.com/5723986

Ian Knowles wrote in message <6bq6d9$4...@netlab.cs.rpi.edu>...


>"Mark Wilden" <Ma...@mWilden.com> wrote:
>
>> Since in
>>general it's easier to read English than C++, I or another reader can
>>get the gist of the function's implementation simply by reading the
>>comments.
>
>In large development environments with many programmers (usually with
>different attitudes and styles to writing comments and quite possibly
>with English as a second language) such comments will often tend to be
>either badly re-worded over time or (worse yet) simply left alone
>while the code around them is re-worked.

Mark Wilden

unread,
Feb 11, 1998, 3:00:00 AM2/11/98
to

Christopher Eltschka wrote in message <6bq6f3$4...@netlab.cs.rpi.edu>...

>
>Well, maybe his tools do it automatically for him.

My point was that in an environment with such useful language-aware tools
naming conventions are likely to be less useful anyway. In the best
environment, I wouldn't need to use naming conventions, because in the few
times I was actually unsure about the scope/type/etc of an identifier, I could
just press a single key and find out.

Andrew Bell

unread,
Feb 11, 1998, 3:00:00 AM2/11/98
to

On 7 Feb 1998 19:03:47 -0500, "Mark Wilden" <Ma...@mWilden.com> wrote:
>Andrew Bell wrote in message <6bi8ks$4...@netlab.cs.rpi.edu>...
>>Renaming
>>existing globals and using naming rules that help make new code more
>>readable under these circumstances is.

>Do you really rename existing globals under these circumstances?

Generally only those that are only used in a single source file.
Using a very liberal definition of renaming (Ok, a completely
inaccurate one), I do at times "rename" it with a function call to
make it easier to figure out where it is modified.

Simon Sadedin

unread,
Feb 11, 1998, 3:00:00 AM2/11/98
to

> Wouldn't it be better to spend the effort convincing people to write
> clear functions rather than applying bandaids like m_?
>
> In good code, it's obvious what are members and what aren't (hint:
> anything that's not a parameter or a local is a member). In bad code,
> I've got a lot bigger problems understanding it than that! :)
>

I think "bandaids" like m_ are important in their own right: they prevent
bugs.
Consider:

class A
{
int x;
void foo();
}

void A::foo()
{
int x=0; // Overrides the class member x!

// lots of lines of code
....
x = 1; // Bug bug bug... did I mean the class member or the local?
}

Of course x is not a "clear" name, but even extravagent names
tend to be repeated if they refer to a similar thing in a similar
context.

Just my 0.02.

Simon Sadedin.

It is loading more messages.
0 new messages