how to recognize whether code is C or C++?

J

James Kanze

I got it from Bjarne Stroustrup, in The C++ Programming
Language. It's not poor style.

Style is a matter of taste. I know a lot of people who consider
it poor style. I also know some (a minority, but it does
include some experts) who use it systematically: struct if all
members are public.

The only absolute rule here is to use whatever style the other
programmers in your company are using.
Furthermore, it is very popular, which is the exact opposite
of the main claim from your previous post (which you snipped).

I don't know how popular it is. Stroustrup uses it, but I've
not seen many others recommending it. The most frequent rule
seems to be either "use struct for PODS, class for everything
else", or "use struct if there are data members and they are
public, class for everything else". And there are doubtless
other reasonable rules.
"Save" a few keystrokes? That presumes that writing class,
followed by public:, is somehow the natural order of things,
and that using struct deviates from that order. That's
ridiculous; if you don't have any private members, why use a
keyword whose sole purpose is to make a struct's default
access level private?

Because it is the accepted convention where you work.

Like most people (I think), I always start my classes with the
public members. (This is really a questionable policy, but so
many places I've worked in have had it that I tend to do it
automatically.) And still use class, although the first
elements are public. For better or for worse, the words
"struct" and "class" speak to the reader, and you want to use
one which tells the reader the truth, when interpreted as he
interprets it.
That's one possible convention, being your favorite does not
make it "about the only useful reason."
class foo
{
public:
// ...
};
Is more verbose, and IMO no clearer, than:
struct foo
{
// ...
};

Clarity depends on the local conventions. If the local
convention says that "struct" means PODS, then using it for
anything else is less clear.
In the first place, that's a useless warning, since there is
no difference between a class and a struct. They're the same
thing. The keywords just introduce different default access
levels, when used to begin a definition.
In the second place, your compiler may not be configured in a
sane way. GCC, with the warnings cranked up, produces no such
warning, nor should it.

Off hand, I can't find a compiler that warns about it, even with
the warnings cranked up.

In the very distant past, VC++ 6 didn't just warn, it treated it
as an error (IIRC). But seriously, VC++ 6 is decidedly
pre-standard, and while I don't think one should constantly run
to use the latest version of every compiler, there's really no
excuse for going to the opposite extreme, and using compilers
that are more than ten years old (and no longer supported by
their vendor).
In the third place, if you really just want to be consistent,
the thing to change is the forward declaration, not the
definition. The following two declarations are semantically
identical:
class base;
struct base;

The problem is that if the rule depends on the contents of the
class, and you change the contents (in a way that should be
transparent to the user), all client code has to be modified.
In the fourth place, forward declarations smell bad. There's
rarely any good reason to start declaring code to work with
classes whose definitions have not even been seen.

Forward declarations reduce coupling and dependencies. They
should be used whenever possible. (Of course, if you use the
compilation firewall idiom, you don't even need the forward
declarations.)
It doesn't need to be "fixed," because it isn't broken. If
you need to work with a type that hasn't been defined yet, you
can easily give it a name by making it a template parameter.
That's the right thing to do. Then, you don't have to care
whether it's a class name, a typedef, or a primitive type.

But you have introduced significant extra complexity, for
nothing. And in the absense of export, significant extra
coupling. Templates are something to be avoided (except when
the alternatives are worse, of course).
 
J

James Kanze

They may seem the same, and should be the same, but at least
one compiler has alway rejected it if it doesn't match the
actual definition.

The only compiler I know which rejected it hasn't been around
for seven or eight years. All of the current versions I have
access to accept it.
Oh really? Guess Sutter shouldn't have recommended them on
his GotD site and his Exceptional C++ books.

Actually, Sutter isn't alone here---he's basing his
recommendations on Lakos. For once, every expert I know seems
to be in agreement here.
 
J

James Kanze

Can you state any technical reason for that guideline or is
this yet another irrational standard you like to harp on?

Communicating information to the reader? That's the "technical
reason" behind most guidelines. (The compiler doesn't care if
we indent, either, or even if we put the entire class definition
on a single line. Readers do.)
What happens when what used to be a "behaviorless data bucket"
suddenly gains behavior?

You've broken client code expectations, so all client code has
to be re-reviewed, and probably updated.
Is a "behaviorless data bucket" really an object that has
enough responsibility to survive?

It depends on what you mean by "behaviorless data bucket", and
whether C compatibility is an issue.
Is a C language structure that has member function pointers a
class or not?
Is this a class?
class X
{
int x;
friend ostream& operator<<(ostream&,X const&);
};

It's not even usable, since it only has a default
constructor:).
Is this less of a class?
struct X
{
int x;
};
ostream& operator<<(ostream&,X const&);

According to the language, they're both classes. A user will
doubtlessly use them in different ways, however.
Is this a class?
class X
{
public:
int x;
X() : x(42) {}
};
Why put it together with the former?

Because they're both common guidelines.
There's no reason to use 'class' over 'struct' since they mean
the same thing.

To the compiler. Not to the human reader.

[...]
As I learned the other day, even a union is a "class" in C++.

According to the standard. In practice, there's is a clear
distinction between unions and other classes (and you can't
forward declare a union with "class" or "struct", or vice
versa).
Since the only difference between 'struct' and 'class' in C++
is default permission, and it is more common to inherit
publicly and write public members first, it is more efficient
and sensible to use the 'struct' keyword for everything.

Efficient in what sense. Although it pleases me to see that
finally someone has enough sense to use the word for something
other than runtime efficiency (since I'm sure you didn't mean
that), I would like to know what efficiency you are talking
about. Since you have two distinct keywords, it would seem to
me that "efficiency" argues in favor of giving them different
meanings, even if the language doesn't.
This does two things:
1. saves us from the pointless typing of 'public' everywhere.

Whoopy do.
2. Points out uncommon inheritance by using keywords for the
uncommon permission rather than the common one.

In practice, that rules seems little enough known that it makes
sense to always specify access in inheritance. At least, except
for demonstrations in standards discussions, I've never seen
anyone not specifying access in inheritance.
The standards committee could do us all a favor and get rid of
the 'class' keyword all together.

Or making class and struct mean two different things. Or doing
any other number of things which would in fact break all
existing C++ code.

I don't call that a favor.
 
J

James Kanze

I first saw it in Java.

Java's a significantly different language than C++. Java
doesn't allow good separation of code and specification to begin
with. For better or for worse (mostly for worse, IMHO, but
that's a different argument), a lot of C++ projects tend to use
header files for documentation. And in that case, it does make
a lot of sense to put the public members first.
 
J

James Kanze

Jeff Schwab wrote:
I've always written my classes that way. I find it much more
natural to look up the screen for declarations than down. We
do this everywhere else in our code, so why should class
declarations be any different?

Because in far too many shops, they don't write class
documentation before writing the class itself. And far too
often, the class definition, in the header file, is the only
documentation you have for the class.

As for the position on the screen, when I'm working, the
declarations are above the actual code where they are used.
They're in separate windows in gvim, so I can put them where
ever I want. (Since the two are in separate files to begin
with, I couldn't put them in the same window, even if I wanted.)
One could argue writing the public interface before the
private data it uses is akin to top posting.....

I don't really see the relationship. The code which uses the
declarations is not even in the same file.
 
J

James Kanze

[...]
Writing the public interface first puts the most interesting
and important information about an interface as the first
thing you see.

In a well organized shop, the *only* thing I'll see of a class
is its documentation, unless I'm actually maintaining the class
(and even then, I won't look at the class definition itself
until I've understood the documentation).

Of course, in the real world, things aren't always that well
organized, and you're right.
Implementation details, such as private member variables,
rarely need to be accessed or read. One would prefer they not
be in the interface at all, and you can use pimpl's to make
that happen, but this is C++ so we must make do. If you are
using a pimpl then it makes even less sense to have that as
the top most item of importance in a class declaration since
it's completely meaningless to the interface.

An interesting (maybe), although purely anecdotal data point:
when I use the compilation firewall idiom, the implementation
class often will be declared "struct", i.e.:

Toto.hh:
class Toto
{
public:
// ...
private:
class Impl ;
Impl* myImpl ;
} ;

Toto.cc:

struct Toto::Impl
{
// ...
} ;

But of course, it's not rare for the Impl class to contain
mainly public data as well.
 
J

James Kanze


As if I didn't know:). I actually use :split when dealing with
local classes (defined in the source file), just as you say.

Oh well, we all have off moments when we forget something vital,
that we know perfectly.
 
J

James Kanze

It's ill-formed. When the compiler encounters an ill-formed
construct, the language definition requires that the compiler
issue a diagnostic. A diagnostic is any message from an
implementation-defined set of messages. The language
definition does not distinguish between warnings, errors, or
valentines.

It also does not say where that message appears. A perfectly
conforming implementation could define that message to be "The
guy who wrote this is an idiot", and the medium to be an email
to your boss. (Luckily, no place I've worked has used such a
compiler.)

There's also nothing which forbids a compiler from issuing a
diagnostic for perfectly legal code. GCC documents that
"Diagnostics consist of all the output sent to stderr by GCC"
(for C, anyway), which definitly includes warnings. And some of
those warnings are for perfectly legal code. (Depending on the
options, some are for perfectly normal and idiomatic code.)

So a compiler which always outputs a single "?", regardless of
the program it is compiling, is perfectly conformant, if it
documents that "?" is its implementation defined diagnostic.

(Note to that its undefined behavior if your program exceeds a
resource limit. So all a compiler has to do to be conform is to
set its resource limits ridiculously low, output "?", and be
done with it. A one line shell script, in sum.)
It also does not require compilers to refuse to compile
ill-formed code (that's the hook for compiler-specific
extensions: issue a diagnostic, then do the extension).

In fact, what happens after the diagnostic is undefined
behavior. I once heard it suggested that the compiler could
define the diagnostic to be that the red light on your hard disk
lights up for 1 second per MB (back then). The result of the
undefined behavior happened to be that your hard disk was
reformatted.

All of the above is really meant in fun, of course. The
standard doesn't (and cannot) require that the compiler is in
any way usable, and the standard is only part of the "contract"
with the compiler. Quality of implementation issues do
intervene, really, and although I've seen some pretty bad
compilers in my time, none were actually perverse. (And I don't
loose any sleep over the possibility that my compiler might
reformat my hard disk if I fed it a ill-formed program.)
 
I

Ian Collins

James said:
As for the position on the screen, when I'm working, the
declarations are above the actual code where they are used.
They're in separate windows in gvim, so I can put them where
ever I want. (Since the two are in separate files to begin
with, I couldn't put them in the same window, even if I wanted.)

So your compilers support export templates?
 
I

Ian Collins

Pete said:
Maybe, but that's not required by the standard. The standard only
requires a diagnostic.
Fair enough, but do you know any that would accept it?
 
C

coal

Because in far too many shops, they don't write class
documentation before writing the class itself. And far too
often, the class definition, in the header file, is the only
documentation you have for the class.

I don't dispute your assertions, but don't find your
conclusion persuasive.
As for the position on the screen, when I'm working, the
declarations are above the actual code where they are used.
They're in separate windows in gvim, so I can put them where
ever I want. (Since the two are in separate files to begin
with, I couldn't put them in the same window, even if I wanted.)


I don't really see the relationship. The code which uses the
declarations is not even in the same file.

Don't forget about header only libraries like the Boost
Intrusive library --
http://www.boost.org/doc/libs/1_39_0/doc/html/intrusive.html.


Brian Wood
Ebenezer Enterprises
www.webEbenezer.net
 
J

James Kanze

So your compilers support export templates?

No:). But it's still quite possible (and generally
preferable) to put the template implementation in a separate
file; you just have to include that file from the header,
rather than compiling it separately. (And of course,
templates are a special case---most programmers shouldn't be
defining them anyway.)
 
N

Noah Roberts

James said:
Communicating information to the reader? That's the "technical
reason" behind most guidelines.

Duh! So far though, there's been no argument from the poster that this
guideline does address communication. In fact, it is my argument that
it communicates falsehood.
You've broken client code expectations, so all client code has
to be re-reviewed, and probably updated.

Before change:

struct DataBucket
{
int x;
char q;
};

After change:

struct DataBucket
{
int x;
char q;

print();
};


I see no client breaking changes.
To the compiler. Not to the human reader.

When in argument, the human rarely wins.
 
J

James Kanze

James said:
Phlip wrote:
Ian Collins wrote: [...]
Can you state any technical reason for that guideline or is
this yet another irrational standard you like to harp on?
Communicating information to the reader? That's the
"technical reason" behind most guidelines.
Duh! So far though, there's been no argument from the poster
that this guideline does address communication. In fact, it
is my argument that it communicates falsehood.

It communicates what the local conventions say it communicates.
Regardless of the local conventions, of course, it can be used
to lie, but that's a separate issue.
Before change:
struct DataBucket
{
int x;
char q;
};
After change:
struct DataBucket
{
int x;
char q;

print();
};
I see no client breaking changes.

And I see no real reason to change struct to class---it's still
a POD. And it can still be used as a data bucket.

Add a constructor, and the issue changes: algomerate
initialization is no longer valid, and there's no way to ensure
static initialization. In some conventions, that's sufficient
to change the "struct" to "class". (In the convention I use in
my own code, either all data members are private, or all are
public. I use class in the first case, and struct in the
second. If there are no data members, I'm somewhat ambivalent;
I'll generally use class if there are non-static member
functions, and struct otherwise.)
When in argument, the human rarely wins.

But there's no argument, since the compiler doesn't care.
 
N

Noah Roberts

James said:
And I see no real reason to change struct to class---it's still
a POD. And it can still be used as a data bucket.

First, that's not what the poster to whom I replied stated. They didn't
say POD. If you want to change the topic that's fine, but don't pretend
that's a refutation.

Second, 'class' can also be a POD. PODness actually depends very little
on anything that should be considered high level enough to be deciding
code standard issues. It isn't a matter that depends solely on design
semantics but on low-level language semantics. If you decide to make
all PODs structs and all non-PODs classes, you'll find that a lot of
structures that people would normally consider classes (in an OO sense)
need to be structs.

It is better to just consider them the same thing, since they in fact are.
Add a constructor, and the issue changes: algomerate
initialization is no longer valid, and there's no way to ensure
static initialization.

The declaration of a struct or class is sufficiently removed from usage
sites in most cases to make the distinction insufficient to
communicating this difference.
But there's no argument, since the compiler doesn't care.

That IS the argument. Human says it matters, compiler says it doesn't.
Compiler wins. How does it win? Because you'll find it provides no
indication you're using struct/class in a manner that violates whatever
distinction you have made up. A 'struct' that has "become" a 'class'
can slip by the compiler with no warning whatsoever.
 
B

Bart van Ingen Schenau

When in argument between a compiler and a human reviewer, the one that
takes the strictest view wins.
If the human reviewer imposes more requirements on the code than the
compiler, the human invariably wins (if only because he refuses to sign-
off on your code).
That IS the argument. Human says it matters, compiler says it
doesn't.
Compiler wins. How does it win? Because you'll find it provides no
indication you're using struct/class in a manner that violates
whatever
distinction you have made up. A 'struct' that has "become" a 'class'
can slip by the compiler with no warning whatsoever.

By that reasoning, this is perfect code, because the compiler accepts
it:

#include<stdio.h>
int main(int,const char**v){goto L8;L2:return 99;L3:if((*v)[0])goto
L6;else goto L2;L4:v[0]++;L5:goto L3;L6:putchar(**v);goto
L4;L8:v[0]="hello, world\n";goto L5;}

It compiles cleanly and works as expected, so there can not be any
hindrance in putting this code in the production archive. Or is there?

Bart v Ingen Schenau
 
N

Noah Roberts

Bart said:
When in argument between a compiler and a human reviewer, the one that
takes the strictest view wins.
If the human reviewer imposes more requirements on the code than the
compiler, the human invariably wins (if only because he refuses to sign-
off on your code).

The fact that there are pointless standards does not legitimate
pointless standards. The argument is not about whether or not some code
will pass someone's silly idea of what should be done, but whether they
should be imposing this meaningless standard.
That IS the argument. Human says it matters, compiler says it
doesn't.
Compiler wins. How does it win? Because you'll find it provides no
indication you're using struct/class in a manner that violates
whatever
distinction you have made up. A 'struct' that has "become" a 'class'
can slip by the compiler with no warning whatsoever.

By that reasoning, this is perfect code, because the compiler accepts
it:

#include<stdio.h>
int main(int,const char**v){goto L8;L2:return 99;L3:if((*v)[0])goto
L6;else goto L2;L4:v[0]++;L5:goto L3;L6:putchar(**v);goto
L4;L8:v[0]="hello, world\n";goto L5;}

It compiles cleanly and works as expected, so there can not be any
hindrance in putting this code in the production archive. Or is there?

I'll clue you into the difference.

The above is pretty much illegible. However, the scope of the problem
is rather limited. If there are functions elsewhere that have adequate
formatting, they are not impacted by the problem of reading main(). As
far as working on that code is concerned, main is not a problem since
main is not meant to communicate anything beyond itself.

Those claiming 'struct' needs to be used to communicate some sort of
whatever (nobody seems to agree on what) are primarily claiming that it
is meant to communicate issues that ARE meant to go beyond the scope of
declaration. You can be miles away from the part of the code meant to
inform you of something and be completely unaware of this.

In other words, the struct problem is one of point A attempting to
communicate something to point B, with nothing at point B to indicate
this communication is taking place; there's a disconnect. Your screwed
up main function is not such a situation.

Claiming that apples should all be red because oranges are orange is not
convincing.
 
K

Keith Thompson

Alf P. Steinbach said:
* Jeff Schwab:

It's unnecessary to make the header code incompatible with C++ on such
a obvious issue.

Maybe. Or maybe there was a legitimate reason. Perhaps the code was
subtly incompatible with C++ in some way, and using "class" as an
identifier prevents someone from accidentally using it from C++.

(I'm not saying it's likely, but it's conceivable.)
It's like when designing a door to your house: even if you and your
wife are both short people (short people, short people! :)[1]) you
design that door so that other people can just walk in without risking
banging their head.

Or, I would, if I were that short and were designing a door.

Ah, but if you don't like tall people ...
 
K

Keith Thompson

Sherm Pendley said:
The file name. Why would a C++ file have a .c extension to begin with?

Some C++ files have a ".C" extension, and some operating systems /
file systems doesn't distinguish between upper and lower case. And
using ".h" for C++ headers is more common than using ".c" for C++
source files.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top