Confusion about .h and .cpp files

S

Stu Cotts

I am moving from Delphi to Visual C++ (vis studio 2003).

I always thought header files were for prototyping only and the cpp file was
for code

All (managed) C++ code samples I have seen (from MSDN), the cpp file is
basically empty and everything is in the .h file.

I have the Visual Studio C++ step by step book which for 2002, before form
creation in 2003. All example put class definition in the cpp file and most
files don't even have headers....

I am confused, can anyone shed light, and/or where I can get info

Am I the only one confused???

Do people do managed C++ or are people only using VS C++ for MFC?

Thanks,
Stuart
 
C

Carl Daniel [VC++ MVP]

Stu said:
I am moving from Delphi to Visual C++ (vis studio 2003).

I always thought header files were for prototyping only and the cpp
file was for code

Headers are for code that is shared between translation units. Cpp files
are the main bodies of translation units. Even that is mere convention - to
the compiler they're all simply source files.
All (managed) C++ code samples I have seen (from MSDN), the cpp file
is basically empty and everything is in the .h file.

This is the style used by the Windows Forms wizards (and the examples)
because they were designed for C# which does not use separate files for
declaration and definition.
I have the Visual Studio C++ step by step book which for 2002, before
form creation in 2003. All example put class definition in the cpp
file and most files don't even have headers....

Nearly every C or C++ source file will include one or more other files
("headers"). It's not particularly uncommon for a particular foo.cpp to
have no corresponding foo.h.
I am confused, can anyone shed light, and/or where I can get info

Just remember: "headers" are a convention for source code organization -
nothing more. There's no magic set of rules for what "needs" to be in a
header and what "needs" to be in a CPP file. If you'd like a set of rules,
I'd suggest the book "Large Scale C++ Software Design" by John Lakos, or
"Code Complete" by Steve McConnell.
Am I the only one confused???

No, you're not - this question comes up regularly.
Do people do managed C++ or are people only using VS C++ for MFC?

People do do managed C++, and many other things in C++ aside from MFC.
Thanks,
Stuart

-cd
 
A

Arnold the Aardvark

This is mostly right. But it is possible to write functions 'inline',
which is a hint to the compiler to substitute the function call with the
body of the function. This can lead to a performance increase in some
circumstances, but may increase the size of the generated code.

The compiler needs to see the body of the function in any translation unit
that calls it if it is going to inline it, so inline functions have to go
in the header (or be included by it). It is still preferable to define them
outside the class, though:

// in header
class Class
{
void Foo() { /* do something */} // implicitly inline, like C#.
void Bar();
};

// explicitly inline - preferred
inline Class::Bar()
{
/* do something */
}

Inlining is a *hint*. The compiler will ignore it for complex functions.
And to do it routinely is an early optimisation which, as we all know,
is the root of all evil.
Just remember: "headers" are a convention for source code organization -
nothing more.

This is very bad advice, and plain wrong in some circumstances (see below).
C++ has a one-definition rule. Try putting the body of a non-inline
function in a header and including it in more than one translation unit.
The linker will not link.

The semantics of inline code are different in Java and C#. Don't be misled.
In C++ it is an explicit hint to the compiler, which it is free to ignore.
In Java and C# it is just the way the code must be organised - a serious
design flaw IMO because this mixes the interface with the implementation.
I don't know whether any actual inlining occurs or not.

[FWIW, I can't understand why the designers of these languages did not
adopt the Pascal notion of a single file but still separating interface
from implementation. This is a strength in Delphi code.]
This is the style used by the Windows Forms wizards (and the examples)
because they were designed for C# which does not use separate files for
declaration and definition.

Which is the same as saying that MS don't understand or don't care about
C++. C++Builder has a superior forms based IDE and maintains a proper
separation of H and CPP code, so it is obviously possible. Different
languages have different requirements. It is ridiculous to say "one size
fits all."
There's no magic set of rules for what "needs" to be in a header and what
"needs" to be in a CPP file.

There most definitely are such rules. For example a static data member must
be defined somewhere (the header contains a declaration). This must be in
a single translation unit because of the one-definition rule. This basically
means you must stick it in one of your CPPs.
I'd suggest the book "Large Scale C++ Software Design" by John
Lakos, or "Code Complete" by Steve McConnell.

This is very good advice. Not only are there a few rules which must be
followed, but there are a great many "best practice" ideas which lead to
better separation and reduced dependencies between translation units.
Lakos is particularly valuable in this regard.

Don't get too bogged down by this. You won't go far wrong if in your mind
you map Delphi's interface section to a header, and the implementation
section to a CPP.

Finally, I'd give Managed C++ a miss altogether if I were you and learn C#
instead. Use Standard C++ for C++ projects, not the kludge that MS has
created, which is emphatically NOT C++. C## would be a better name.


Arnold the Aardvark

'And no, C++ does not have "garbage collection".
Thank God for that. C++ gives me the ability to not
create garbage in the first place.' - Ed Mulroy
 
C

Carl Daniel [VC++ MVP]

Arnold said:
This is very bad advice, and plain wrong in some circumstances (see
below). C++ has a one-definition rule.

It's not advice - it's a fact. Headers have no meaning to the language or
the compiler, and it's possible to build a program of arbitrary complexity
without using a single header. Not that anyone would want to. Headers ARE
a convention for source code organization - nothing more. When used
according to a consistent and purposeful set of organizationl patterns
headers are an essential part of lage-scal code organization.
Try putting the body of a
non-inline function in a header and including it in more than one
translation unit. The linker will not link.

Try putting the same body in two cpp files - it also will not link. The
problem (ODR violation) is not intrinsically realted to header files at
all - inappropriate construction of header files simply makes it easier to
create ODR violations.
Which is the same as saying that MS don't understand or don't care
about C++.

It's easy to get into that mindset, but assigning motivation by observable
behavior is a tricky business. It's also the same as saying that Windows
Forms was developed by the C# team and there wasn't time to re-write the
designers to fully support typical C++ code organization practices.
There most definitely are such rules.

Not as a part of the C++ language there aren't. The rule that people accept
as gospel for C++ development are code organization rules that help you
write correct C++ code. There's nothing in the language that requires
anything in particular to be in "header" files, or to even use them at all.
For example a static data
member must be defined somewhere (the header contains a declaration).
This must be in
a single translation unit because of the one-definition rule. This
basically means you must stick it in one of your CPPs.

You could just as well stick it in a "header" that's included in only one
cpp file. Again, not that you'd want to, but from a language standpoint
it'd be perfectly fine.

-cd
 
T

TOM

The subject is not discussed sufficiently in the step-by-step books. When I
was
starting with .NET, even one example would have helped! .NET seems to handle
it all properly. I find that using header files helps a lot with some
issues:

1. A header should expose only enough information about an object to use it.
This (theoretically) allows changing the internal implementaiton of an
object
(in the C++ file) without breaking code that uses the object (through the H
file).
In C++ it seems you have to declare all the private members as well in the H
file,
then the compiler enforces the private access rule.

2. A header file can break #include conflicts. This is a big problem with
legacy code,
since .NET (in my view) seems to have lots of conflicts with headers from
older code.
I have been fighting one such problem for months. Finally hid all code that
uses older
system calls in one object, then only have to include a forward reference to
that
object (i.e. __gc class public Object_that_encapsulates_old_system_calls).
This puts all the #includes only in the CPP file that builds that object,
and the #includes
do not get spread to your other modules.

-- Tom
 
A

Arnold the Aardvark

OK. I stand corrected regarding the C++ language itself. I'm
not much of a language lawyer, anyway.

However, I maintain that arguing about what is theoretically
possible, but exceedingly bad practice, is no use whatsoever
to a newby trying to understand what's going on. Separate
compilation of objects and inter-object references (via headers)
are a fact of life for almost every project. This makes
understanding what does and does not go in a header vitally
important.

When you have 10 million lines of code and implement a function
inline that is called from hundreds of translation units, what
happens when you change the function? You wait hours for the
code to make after a trivial change. I don't like such a long
wait. YMMV. And all the clients of your library have to recompile
their projects too. This is a Bad Thing.

The fact is that VC++.NET IDE gets this badly wrong, and
that the OP was largely correct is in his understanding.
Obviously it compiles, but it is not a model the OP should
consider following. I did not think your comments were terribly
helpful - sorry.

If the OP wants to follow Lakos' excellent advice, he will
probably find that the VC++.NET IDE constantly gets in his
way. I'd call that a broken IDE.
You could just as well stick it in a "header" that's included in only one
cpp file. Again, not that you'd want to, but from a language standpoint
it'd be perfectly fine.

Semantics. How do you ensure that the file in included in only one
translation unit? I hope you don't write such bad code as easily as
you defend it.


Arnold the Aardark
 
W

William DePalo [MVP VC++]

Arnold the Aardvark said:
OK. I stand corrected regarding the C++ language itself. I'm
not much of a language lawyer, anyway.
Gotcha.

However, I maintain that arguing about what is theoretically
possible, but exceedingly bad practice, is no use whatsoever
to a newby trying to understand what's going on. Separate
compilation of objects and inter-object references (via headers)
are a fact of life for almost every project. This makes
understanding what does and does not go in a header vitally
important.

On the question of best practices, Carl wrote this:

<quote>
If you'd like a set of rules, I'd suggest the book
"Large Scale C++ Software Design" by John Lakos,
or "Code Complete" by Steve McConnell.
</quote>

Newbies would be wise not to discount the wisdom of their elders. :)

On the other hand all of the C (B?) derived languages C, C++, Objective C,
Managed C++ etc have always preferred to give their developers enough rope
to hang themselves over dumbing the environment down to the point of being
"child proof". It is this mindset that gives those languages a good deal of
their power. It also raises the barrier to entry. Those points, as Martha
might say, are "good things". <bseg>

In my view, it is only when one understands the finer points of the
language, like the artificial distinction between header and source files
that Carl described, that one can become proficient in it.

As to the behavior of the IDE not following best practices, I frankly think
it sucks. I think that it's due to the fact that not all of the Visual
Studio .Net environment was written by the C++ elite. ;-) Every time I run
the debugger in mixed mode I become more convinced of that.

Regards,
Will
 
A

Arnold the Aardvark

William said:

I'm glad you are amused. The point was that ...
As to the behavior of the IDE not following best practices, I frankly
think it sucks.

.... it seemed to me Carl was defending this, which does suck. This
is not helpful to C++ newbies.


Arnold the Aardvark

If you're a civilian, and dead, you must have been a terrorist.
 
W

William DePalo [MVP VC++]

Arnold the Aardvark said:
I'm glad you are amused. The point was that ...

I didn't mean any offense.
... it seemed to me Carl was defending this, which does suck. This
is not helpful to C++ newbies.

I didn't read in his reply a defense of behavior. He pointed out that the
only difference between source and header comes from people's expectations.

The issue with the IDE has come up before. Previously we didn't have a forms
wizard for MC++. Now we have one. That's the good news. The bad news is that
it shows its C# heritage.
If you're a civilian, and dead, you must have been a terrorist.

Not very funny in light of what happened two days ago.

Regards,
Will
 
C

Carl Daniel [VC++ MVP]

Arnold said:
I'm glad you are amused. The point was that ...


... it seemed to me Carl was defending this, which does suck. This
is not helpful to C++ newbies.

I didn't intend to defend it - only to explain it. Personally, I don't
think the WinForms designer practice of putting the implementation in the
header file is nearly as evil as many make it out to be, but that's because
in my designs, the code that ends up there is 1) very tightly coupled to the
UI itself and 2) doesn't do any real work. As a result, that header file is
included in exactly 1 cpp file. YMMV.

-cd
 
A

Arnold the Aardvark

William said:
Not very funny in light of what happened two days ago.

I refer of course to the behaviour and justifications of the US
and Israeli militaries and governments during the last fifty years,
which have resulted in the deaths of millions of innocents.

I wonder whether if I had said this a few days ago, you would have
commented on the tragic loss of at least 10,000 civilian lives in
Iraq at the hands American barbarians.

But I will make it plainer in future who I am attacking. Thanks.


Arnold the Aardvark
http://www.codeproject.com/cpp/garbage_collect.asp
 
W

William DePalo [MVP VC++]

Arnold the Aardvark said:
I wonder whether if I had said this a few days ago, you would have
commented on the tragic loss of at least 10,000 civilian lives in
Iraq at the hands American barbarians.

If this thread has demonstrated anything it is that you make far too many
assumptions.

The loss of ten thousand cilvians in Iraq is awful and only pales in
comparison to the hundreds of thousands of children's lives lost there due
to US/UN sanctions of a decade earlier. And I know of no US foreign in my
lifetime which has been more totally and completely wrong than its policy in
the Middle East.

Still, this ought to be a place where the discussion is limited to technical
issues.

Regards,
Will
 
A

Arnold the Aardvark

William said:
If this thread has demonstrated anything it is that you make far too many
assumptions.

I did not make an assumption: I wondered aloud. You have answered the
implicit question. Note: I did not start this OT conversation.

Frankly I could not care less what you think of me. No one is perfect,
especially me, and I admitted my earlier error. What more can you ask?
I don't mind looking foolish to further my cause, in this case best
practice programming.

I thought we'd had a debate - I was refuted very handily regarding the
language rules - and from this the OP said he learned something. Not so?
Perhaps I should litter my comments with more smileys...

FWIW I was not offended by the 'Gotcha' comment.


Arnold the Aardvark

"Those who cast the votes decide nothing. Those who count the votes
decide everything." - Stalin (and Diebold Election Systems' motto)
 
S

Steve McLellan

I love this one, it always opens up a can of worms :)

As has been said, the .NET wizard convention isn't what most pre- .NET C++
programmers do, and in common with some of the comments here I find the code
that the .NET wizards generates very different from how I've been taught. A
non .NET C++ book will teach you one way; a .NET book will probably teach
you another. My suspicion is that because the MSDN and most .NET examples
stick all the code inside the header, that will slowly become a convention,
even if it's resisted by the old school, and whether it's "right" or "wrong"
won't matter.

Steve
 

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

Top