Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #11892 > unrolled thread

.h and .cpp

Started byChristopher <cpisz@austin.rr.com>
First post2011-11-28 09:20 -0800
Last post2011-11-30 09:23 +1300
Articles 20 on this page of 46 — 17 participants

Back to article view | Back to comp.lang.c++


Contents

  .h and .cpp Christopher <cpisz@austin.rr.com> - 2011-11-28 09:20 -0800
    Re: .h and .cpp Leigh Johnston <leigh@i42.co.uk> - 2011-11-28 17:30 +0000
      Re: .h and .cpp Christopher <cpisz@austin.rr.com> - 2011-11-28 10:39 -0800
        Re: .h and .cpp Tobias Müller <troplin@bluewin.ch> - 2011-11-28 19:09 +0000
    Re: .h and .cpp ralph <nt_consulting64@yahoo.net> - 2011-11-28 12:37 -0600
      Re: .h and .cpp Christopher <cpisz@austin.rr.com> - 2011-11-28 10:48 -0800
        Re: .h and .cpp ralph <nt_consulting64@yahoo.net> - 2011-11-28 14:24 -0600
        Re: .h and .cpp yatremblay@bel1lin202.(none) (Yannick Tremblay) - 2011-11-30 11:24 +0000
          Re: .h and .cpp Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-12-01 21:42 +0000
            Re: .h and .cpp Rui Maciel <rui.maciel@gmail.com> - 2011-12-02 02:03 +0000
              Re: .h and .cpp Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-12-02 20:59 +0000
    Re: .h and .cpp "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2011-11-28 19:45 +0100
      Re: .h and .cpp Leigh Johnston <leigh@i42.co.uk> - 2011-11-28 19:03 +0000
        Re: .h and .cpp "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2011-11-28 20:36 +0100
      Re: .h and .cpp Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-11-28 22:52 +0000
        Re: .h and .cpp yatremblay@bel1lin202.(none) (Yannick Tremblay) - 2011-11-30 11:39 +0000
          Re: .h and .cpp Juha Nieminen <nospam@thanks.invalid> - 2011-11-30 12:50 +0000
            Re: .h and .cpp yatremblay@bel1lin202.(none) (Yannick Tremblay) - 2011-11-30 13:57 +0000
              Re: .h and .cpp Juha Nieminen <nospam@thanks.invalid> - 2011-11-30 15:06 +0000
            Re: .h and .cpp Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-11-30 16:21 +0000
          Re: .h and .cpp Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-11-30 16:12 +0000
    Re: .h and .cpp Goran <goran.pusic@gmail.com> - 2011-11-28 10:58 -0800
      Re: .h and .cpp Christopher <cpisz@austin.rr.com> - 2011-11-28 13:30 -0800
        Re: .h and .cpp Tobias Müller <troplin@bluewin.ch> - 2011-11-29 06:44 +0000
        Re: .h and .cpp Goran <goran.pusic@gmail.com> - 2011-11-29 01:17 -0800
        Re: .h and .cpp Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-11-30 00:53 -0800
      Re: .h and .cpp "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2011-11-29 10:57 +0100
      Re: .h and .cpp yatremblay@bel1lin202.(none) (Yannick Tremblay) - 2011-11-30 12:05 +0000
    Re: .h and .cpp Rui Maciel <rui.maciel@gmail.com> - 2011-11-28 20:07 +0000
    Re: .h and .cpp Geoff <geoff@invalid.invalid> - 2011-11-28 12:17 -0800
      Re: .h and .cpp Ian Collins <ian-news@hotmail.com> - 2011-11-29 11:41 +1300
        Re: .h and .cpp gwowen <gwowen@gmail.com> - 2011-11-29 07:37 -0800
      Re: .h and .cpp Goran <goran.pusic@gmail.com> - 2011-11-29 00:08 -0800
      Re: .h and .cpp Daniel <danielaparker@gmail.com> - 2011-11-29 08:31 -0800
        Re: .h and .cpp ralph <nt_consulting64@yahoo.net> - 2011-11-29 14:49 -0600
          Re: .h and .cpp Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-11-30 00:21 +0000
    Re: .h and .cpp Andy Champ <no.way@nospam.invalid> - 2011-11-28 21:30 +0000
    Re: .h and .cpp Paavo Helde <myfirstname@osa.pri.ee> - 2011-11-28 18:05 -0600
    Re: .h and .cpp Paavo Helde <myfirstname@osa.pri.ee> - 2011-11-28 18:27 -0600
    Re: .h and .cpp Juha Nieminen <nospam@thanks.invalid> - 2011-11-29 07:55 +0000
      Re: .h and .cpp Christopher <cpisz@austin.rr.com> - 2011-11-29 12:15 -0800
        Re: .h and .cpp Leigh Johnston <leigh@i42.co.uk> - 2011-11-29 20:19 +0000
          Re: .h and .cpp Christopher <cpisz@austin.rr.com> - 2011-11-29 12:31 -0800
            Re: .h and .cpp Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-11-30 00:31 +0000
          Re: .h and .cpp Juha Nieminen <nospam@thanks.invalid> - 2011-11-30 09:43 +0000
        Re: .h and .cpp Ian Collins <ian-news@hotmail.com> - 2011-11-30 09:23 +1300

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#11982

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2011-11-30 16:12 +0000
Message-ID<slrnjdclf5.1bk.grahn+nntp@frailea.sa.invalid>
In reply to#11976
On Wed, 2011-11-30, yatremblay@bel1lin202.(none) (Yannick Tremblay) wrote:
> In article <slrnjd845a.1bk.grahn+nntp@frailea.sa.invalid>,
> Jorgen Grahn  <grahn+nntp@snipabacken.se> wrote:
>>On Mon, 2011-11-28, Alf P. Steinbach wrote:
>>>
>>> For example, with Visual C++ use at least /W4, and with g++ use at least 
>>> -Wall
>>
>>I've mentioned it before, but IMHO -Wall is far from enough. I default
>>to
>>
>>-Wall -Wextra -pedantic -std=c++98 -g -O3
>
> You weakling! "Real Men" use:
>
> -Wall -Wextra -pedantic -std=c++98 -Weffc++ -Wold-style-cast -Werror
>
> :-)

You have a point -- I include -Wold-style-cast these days, and I
should really fix whatever Makefile I quoted from.

(To non-g++ users: -Wold-style-cast means "warn for uses of C-style
casts".)

/Jorgen

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

[toc] | [prev] | [next] | [standalone]


#11898

FromGoran <goran.pusic@gmail.com>
Date2011-11-28 10:58 -0800
Message-ID<72e0c6ca-1269-4e1d-9cf9-be78ec0c4584@y6g2000yqe.googlegroups.com>
In reply to#11892
On Nov 28, 6:20 pm, Christopher <cp...@austin.rr.com> wrote:
> If you were on a team of developers that had little C++ experience,
> how would you go about explaining the reasoning as to why the
> following rules should be followed? (Or why they shouldn't)
>
> 1) Class defintions go in their own .h (or .hpp for templates) file
> named after the class

Don't know about hpp for templates. It's *.h or *.hpp for everything
if you ask me. If there is only one class ion the file, or if it's
clearly the "main" class in it, then class_name.h is only natural.

> 1a) Every class should have its own .h (or .hpp for templates) file

Not so sure about that. All sorts of auxiliary artifacts can just as
well be tagged along their principal stuff.

> 1b) A .h file should never contain class implementation (except for
> inline functions or methods)

Purely mechanically, this doesn't work due to C compilation model: if
the class parts are defined in a header, and said header is included
in more than one translation unit (source file), linker will encounter
duplicate symbols.

> 2) Class implementations go in their own .cpp file (except for
> templates)

Same as above

> 2a) A .cpp should never contain a class definition

Disagreed. There's classes that will only be used in one translation
unit. What can one gain by making another trivial header?

> 3) One should not define multiple classes in a single .h file
> 3a) Nested class defintions should be avoided without good reason
> (what's good reason?)

Good reason: nested class is used exclusively in context of the
nesting class, possibly as a helper.

Private nested classes should be avoided. They are better off in
implementation file, as not to create additional compile-time
dependency where there's no logical one.

> 6) Variables should never be defined in a .h file

Same as for classes - duplicate symbols galore. Exception: literal
constants. If these are not constants, there should ideally be 0 of
those in any given codebase.

> 7) Globals should not be defined in a .h file

I am not sure to understand the difference between a variable and a
global?

> 8) Every .cpp file should compile into a .obj file without error or
> warning on its own.
>      i.e In Visual Studio, you should be able to right click a .cpp in
> the source tree and choose compile, without error or warning in the
> output.

Except for precompiler header, which one should be using to save
compilation time. IOW, if precompiled header is used and compiled,
then any translation unit should compile.

Otherwise, if you can't compile without errors, you can't compile, end
of, so that's a given. As for warnings... When compiler emits a
warning, it does it for a reason. Coder isn't smarter than compiler as
far as formal verification goes. If there's a warning, coder should
first try to change the code so that compiler has no reason for
nagging. That usually ends in a better design. Casting or other
compiler-gagging come distant second as idea.

> Sadly, I find myself having to justify these things.

Sadly is a good word. What, do directory entries cost these people
money?

> (of course
> someone might point out I am wrong or exceptions to the above), but
> these are things that I've always had drilled into my head throughout
> the years and have rarely come acorss other developers that didn't do
> the same. I am finding it frustrating to work on a project where 30
> classes defintions reside in the .h same .h file, a single .cpp file,
> or worse a precompiled header. There is discussion, but I have to
> explain reasoning.

Ugh. That's a clear-cut sign that someone doesn't know how to work
with C compilation model.

Goran.

[toc] | [prev] | [next] | [standalone]


#11910

FromChristopher <cpisz@austin.rr.com>
Date2011-11-28 13:30 -0800
Message-ID<6d8f5317-464d-4a34-92df-3986d9cc8e29@s4g2000yqk.googlegroups.com>
In reply to#11898
On Nov 28, 12:58 pm, Goran <goran.pu...@gmail.com> wrote:
> > 1a) Every class should have its own .h (or .hpp for templates) file
>
> Not so sure about that. All sorts of auxiliary artifacts can just as
> well be tagged along their principal stuff.

I suppose a functor used for comparison might be an example. I need to
explain somehow what kinds of things would be an auxilary artifact
that is acceptable and what obviously requires seperation. I suppose
it is just intuitive to most of us.

I think what was said about nested classes is a good start. If the
class is only used by the main class in the file.


> > 1b) A .h file should never contain class implementation (except for
> > inline functions or methods)
>
> Purely mechanically, this doesn't work due to C compilation model: if
> the class parts are defined in a header, and said header is included
> in more than one translation unit (source file), linker will encounter
> duplicate symbols.
> > 2) Class implementations go in their own .cpp file (except for
> > templates)
>
> Same as above
>

I cannot visualize this scenario. Can you give a code example in which
any part of class implementation is required to be in the header,
excluding the use of templates?

Use of inclusion guards has always taken care of duplicate symbols
when a header is included in more than one source file and is pretty
standard practice in my experience.



> > 2a) A .cpp should never contain a class definition
>
> Disagreed. There's classes that will only be used in one translation
> unit. What can one gain by making another trivial header?

In this case, what's wrong with putting it in the header? I suppose
until I can visualize your argument for 1b and 2, I have trouble
seeing this as well.

When I see an unfamilair type in a source file, I would immeditaley
look in the corresponding .h file for its defintion. I'd hate to rely
on "not-so-intelli-sense" or something similar.

If inclusion guards are used, I don't see the down side.


> > 3) One should not define multiple classes in a single .h file
> > 3a) Nested class defintions should be avoided without good reason
> > (what's good reason?)
>
> Good reason: nested class is used exclusively in context of the
> nesting class, possibly as a helper.

Good reason!


> Private nested classes should be avoided. They are better off in
> implementation file, as not to create additional compile-time
> dependency where there's no logical one.

I could see this making sense pending more explanation to the previous
arguments.


> > 6) Variables should never be defined in a .h file
>
> Same as for classes - duplicate symbols galore. Exception: literal
> constants. If these are not constants, there should ideally be 0 of
> those in any given codebase.

Whoops, I believe I meant to say variable _declaration_. Definition
and Declaration seem to very confusing terms as they have different
meanings for classes and variables in C++.

What I mean is
int x = 10; should not appear in a .h file.
int x; However, may appear in a .h file, but I'd still argue that
there is probably a better way then using a global.

const int x = 10; Should not appear in a .h file
const int x; May appear in a .h file, but I'd rather see:

static int GetX() const
{
   return 10;
}

because some other global MyClass might make use of x and then I run
into the static intialization fiasco.


or better if only used in one class:

class WhereXIsUsed
{
public:
private:
  const int m_x;
};

or possibly something like

struct SystemConfigurationDefaults
{
   const int m_x;
};


> > 7) Globals should not be defined in a .h file
>
> I am not sure to understand the difference between a variable and a
> global?

One is a superset of the other.
But again, I think I meant declared instead.



> > 8) Every .cpp file should compile into a .obj file without error or
> > warning on its own.
> >      i.e In Visual Studio, you should be able to right click a .cpp in
> > the source tree and choose compile, without error or warning in the
> > output.
>
> Except for precompiler header, which one should be using to save
> compilation time. IOW, if precompiled header is used and compiled,
> then any translation unit should compile.

When it comes to precompiled headers, what I am trying to convey is
that everything should compile without them.
Precomiled headers should be used as a build optimization only, if at
all, and not as part of the implementation.

How I've been doing it:

---
/*
* foo.h
*/
#ifndef FOO_H
#define FOO_H

#include <iostream>

// Use of iostream
// SNIP
#endif

---
/*
* foo.cpp
*/
#include "precompiled-header.h"
#include "foo.h"

#include <algorithm>

// Use of algorithm
//SNIP

---
/*
* precompiled-header.h
*/
#include <algorithm>
#include <iostream>
// SNIP

Allows for foo.obj regardless of whether or not the precompiled header
was compiled. If the pre-compiled header was used, it speeds up build
time in some scenarios.


What I've come across that I believe is incorrect, but still compiles
if build order happens to work out:
---
/*
* foo.h
*/
#ifndef FOO_H
#define FOO_H

// Use of iostream
// SNIP
#endif

---
/*
* foo.cpp
*/
#include "precompiled-header.h"

// Use of algorithm
//SNIP

---
/*
* precompiled-header.h
*/
#include "foo.h"

#include <algorithm>
#include <iostream>
// SNIP

My difficulty, assuming I am correct (because I am totally willing to
accept correction with explanation), is expressing this in words.


> Sadly is a good word. What, do directory entries cost these people
> money?

I've heard words like "complexity" and "clutter"
Ironic, because I use words like "simple" and "logical"

[toc] | [prev] | [next] | [standalone]


#11930

FromTobias Müller <troplin@bluewin.ch>
Date2011-11-29 06:44 +0000
Message-ID<55349412344240394.082701troplin-bluewin.ch@news.aioe.org>
In reply to#11910
Christopher <cpisz@austin.rr.com> wrote:
> Use of inclusion guards has always taken care of duplicate symbols
> when a header is included in more than one source file and is pretty
> standard practice in my experience.

Inclusion guards don't help you here, at least if you have more than one
translation unit.

Inclusion guards make sure that you don't have duplicate class definitions
in one TU. However, every header file needs to be visible in every TU or
else you can't use the classes defined in that header. And if you have
method implementations in the header, the code will be generated in every
TU and evetually the linker will complain (not the compiler).

Tobi

[toc] | [prev] | [next] | [standalone]


#11938

FromGoran <goran.pusic@gmail.com>
Date2011-11-29 01:17 -0800
Message-ID<b2b7ea80-4d21-4ab3-a6a6-3f8d50350ddf@s4g2000yqk.googlegroups.com>
In reply to#11910
On Nov 28, 10:30 pm, Christopher <cp...@austin.rr.com> wrote:
> On Nov 28, 12:58 pm, Goran <goran.pu...@gmail.com> wrote:
>
> > > 1a) Every class should have its own .h (or .hpp for templates) file
>
> > Not so sure about that. All sorts of auxiliary artifacts can just as
> > well be tagged along their principal stuff.
>
> I suppose a functor used for comparison might be an example. I need to
> explain somehow what kinds of things would be an auxilary artifact
> that is acceptable and what obviously requires seperation. I suppose
> it is just intuitive to most of us.
>
> I think what was said about nested classes is a good start. If the
> class is only used by the main class in the file.
>
> > > 1b) A .h file should never contain class implementation (except for
> > > inline functions or methods)
>
> > Purely mechanically, this doesn't work due to C compilation model: if
> > the class parts are defined in a header, and said header is included
> > in more than one translation unit (source file), linker will encounter
> > duplicate symbols.
> > > 2) Class implementations go in their own .cpp file (except for
> > > templates)
>
> > Same as above
>
> I cannot visualize this scenario. Can you give a code example in which
> any part of class implementation is required to be in the header,
> excluding the use of templates?

I poorly expressed myself? When I said "same as above", I meant "you
have to put class implementation in it's own implementation because
otherwise linker encounters duplicate symbols". So class
implementations absolutely must go in an implementation file. Perhaps
it's own implementation file (e.g. small related thingy can tag
along).

>
> Use of inclusion guards has always taken care of duplicate symbols
> when a header is included in more than one source file and is pretty
> standard practice in my experience.
>
> > > 2a) A .cpp should never contain a class definition
>
> > Disagreed. There's classes that will only be used in one translation
> > unit. What can one gain by making another trivial header?
>
> In this case, what's wrong with putting it in the header? I suppose
> until I can visualize your argument for 1b and 2, I have trouble
> seeing this as well.

If code artifact is used in only one translation unit, it does not
require a header, that's all. Make it if you wish, but it's only more
files to go around.

> When I see an unfamilair type in a source file, I would immeditaley
> look in the corresponding .h file for its defintion. I'd hate to rely
> on "not-so-intelli-sense" or something similar.

What's wrong with grep or "Find in files" in VS?

> If inclusion guards are used, I don't see the down side.
>
> > > 3) One should not define multiple classes in a single .h file
> > > 3a) Nested class defintions should be avoided without good reason
> > > (what's good reason?)
>
> > Good reason: nested class is used exclusively in context of the
> > nesting class, possibly as a helper.
>
> Good reason!
>
> > Private nested classes should be avoided. They are better off in
> > implementation file, as not to create additional compile-time
> > dependency where there's no logical one.
>
> I could see this making sense pending more explanation to the previous
> arguments.
>
> > > 6) Variables should never be defined in a .h file
>
> > Same as for classes - duplicate symbols galore. Exception: literal
> > constants. If these are not constants, there should ideally be 0 of
> > those in any given codebase.
>
> Whoops, I believe I meant to say variable _declaration_. Definition
> and Declaration seem to very confusing terms as they have different
> meanings for classes and variables in C++.
>
> What I mean is
> int x = 10; should not appear in a .h file.

That doesn't work anyhow. For example (it's the example you're asking
for elsewhere, too), you can compile (BUT NOT LINK)

h.h
#ifndef whatever
#define whatever
int x=10;
#endif

s.cpp
#include "h.h"
void f()
{
  x++;
}

main.cpp
#include "h.h"
int main(int, const char*[])
{
  x++
}

> int x; However, may appear in a .h file, but I'd still argue that
> there is probably a better way then using a global.

I like

extern int x;

(explains the intent better IMO)

> const int x = 10; Should not appear in a .h file
> const int x; May appear in a .h file, but I'd rather see:
>
> static int GetX() const
> {
>    return 10;
>
> }
>
> because some other global MyClass might make use of x and then I run
> into the static intialization fiasco.
>
> or better if only used in one class:
>
> class WhereXIsUsed
> {
> public:
> private:
>   const int m_x;
>
> };

If only used in one class, it's best declared in class's
implementation. That's (for me) to avoid compile-time dependency: you
can change it in *.cpp all you like, you don't recompile all other
*.cpp-s that include your_class.h

>
> or possibly something like
>
> struct SystemConfigurationDefaults
> {
>    const int m_x;
>
> };
> > > 7) Globals should not be defined in a .h file
>
> > I am not sure to understand the difference between a variable and a
> > global?
>
> One is a superset of the other.
> But again, I think I meant declared instead.
>
> > > 8) Every .cpp file should compile into a .obj file without error or
> > > warning on its own.
> > >      i.e In Visual Studio, you should be able to right click a .cpp in
> > > the source tree and choose compile, without error or warning in the
> > > output.
>
> > Except for precompiler header, which one should be using to save
> > compilation time. IOW, if precompiled header is used and compiled,
> > then any translation unit should compile.
>
> When it comes to precompiled headers, what I am trying to convey is
> that everything should compile without them.
> Precomiled headers should be used as a build optimization only, if at
> all, and not as part of the implementation.

Yes, agreed.

> How I've been doing it:
>
> ---
> /*
> * foo.h
> */
> #ifndef FOO_H
> #define FOO_H
>
> #include <iostream>
>
> // Use of iostream
> // SNIP
> #endif
>
> ---
> /*
> * foo.cpp
> */
> #include "precompiled-header.h"
> #include "foo.h"
>
> #include <algorithm>
>
> // Use of algorithm
> //SNIP
>
> ---
> /*
> * precompiled-header.h
> */
> #include <algorithm>
> #include <iostream>
> // SNIP
>
> Allows for foo.obj regardless of whether or not the precompiled header
> was compiled. If the pre-compiled header was used, it speeds up build
> time in some scenarios.

Actually, I like that. I was wrong when I said that you can build
"provided that precompiled header was built before" (and you are
right).

Goran.

[toc] | [prev] | [next] | [standalone]


#11971

FromNick Keighley <nick_keighley_nospam@hotmail.com>
Date2011-11-30 00:53 -0800
Message-ID<d89a97ce-ec8f-411d-b902-3c7f840a34b7@n10g2000vbg.googlegroups.com>
In reply to#11910
On Nov 28, 9:30 pm, Christopher <cp...@austin.rr.com> wrote:
> On Nov 28, 12:58 pm, Goran <goran.pu...@gmail.com> wrote:

<snip>

> > > 1b) A .h file should never contain class implementation (except for
> > > inline functions or methods)
>
> > Purely mechanically, this doesn't work due to C compilation model: if
> > the class parts are defined in a header, and said header is included
> > in more than one translation unit (source file), linker will encounter
> > duplicate symbols.
>
> > > 2) Class implementations go in their own .cpp file (except for
> > > templates)
>
> > Same as above
>
> I cannot visualize this scenario. Can you give a code example in which
> any part of class implementation is required to be in the header,
> excluding the use of templates?
>
> Use of inclusion guards has always taken care of duplicate symbols
> when a header is included in more than one source file and is pretty
> standard practice in my experience.

not if it's in two different compilation units. The key thing is "if
the class parts are /defined/ in a header" (emp. mine). In a nutshell
a declaration of an object (this probably applies to non-objects like
functions as well) says "this is the name of something- but doesn't
allocate any space" whilst a definition gives it soemwhere to live.
Naming something more than once is ok. Creating more than one copy of
something is wrong. This is sometimes referred to as The One
Definition Rule.

> > > 2a) A .cpp should never contain a class definition
>
> > Disagreed. There's classes that will only be used in one translation
> > unit. What can one gain by making another trivial header?
>
> In this case, what's wrong with putting it in the header? I suppose
> until I can visualize your argument for 1b and 2, I have trouble
> seeing this as well.

I'd say don't put it in a header if you don'e need to. It's just work.

<snip>

> > > 6) Variables should never be defined in a .h file
>
> > Same as for classes - duplicate symbols galore. Exception: literal
> > constants. If these are not constants, there should ideally be 0 of
> > those in any given codebase.
>
> Whoops, I believe I meant to say variable _declaration_. Definition
> and Declaration seem to very confusing terms as they have different
> meanings for classes and variables in C++.
>
> What I mean is
> int x = 10; should not appear in a .h file.
> int x; However, may appear in a .h file, but I'd still argue that
> there is probably a better way then using a global.

"global" isn't really a C++ term. ITYM "external". If you are using
them then declare 'em external.

// externals.h
int x;

// externals.c
#include "externals.h"
int x = 10;

// user.c
#include "externals.h"

void f()
{
    doThing (x);
}

> const int x = 10; Should not appear in a .h file
> const int x; May appear in a .h file, but I'd rather see:
>
> static int GetX() const
> {
>    return 10;
>
> }

that should be inline

> because some other global MyClass might make use of x and then I run
> into the static intialization fiasco.

really? This surprises me. Are const items of basic types really
subject to SIF? I thought declaring consts in a header was ok.

    const double PI = 3.1415926535;

I thought the idea was to be able to replace C's

#   define PI 3.1415926535

to have to hide it in a static function seems really icky. I tghink
I'll start using #define again...


> or better if only used in one class:
>
> class WhereXIsUsed
> {
> public:
> private:
>   const int m_x;
>
> };
>
> or possibly something like
>
> struct SystemConfigurationDefaults
> {
>    const int m_x;
>
> };

namespaces maybe?


> > > 7) Globals should not be defined in a .h file
>
> > I am not sure to understand the difference between a variable and a
> > global?
>
> One is a superset of the other.
> But again, I think I meant declared instead.

you also need to expalin what a "global" is. The term is not terribly
well defined.

<snip>

[toc] | [prev] | [next] | [standalone]


#11943

From"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>
Date2011-11-29 10:57 +0100
Message-ID<jb2aa1$g0$1@dont-email.me>
In reply to#11898
On 28.11.2011 19:58, Goran wrote:
> On Nov 28, 6:20 pm, Christopher<cp...@austin.rr.com>  wrote:
>
>> 1b) A .h file should never contain class implementation (except for
>> inline functions or methods)
>
> Purely mechanically, this doesn't work due to C compilation model: if
> the class parts are defined in a header, and said header is included
> in more than one translation unit (source file), linker will encounter
> duplicate symbols.

I think the above is perhaps too vaguely expressed.

First, a "class definition" does not necessarily include definitions of 
member functions.

Secondly, it's quite common to put also definitions of member functions 
in a header. They need then to be either templates or `inline`. For 
example, many Boost sub-libraries are header only.


Cheers & hth.,

- Alf

[toc] | [prev] | [next] | [standalone]


#11977

Fromyatremblay@bel1lin202.(none) (Yannick Tremblay)
Date2011-11-30 12:05 +0000
Message-ID<jb5674$o4u$1@dont-email.me>
In reply to#11898
In article <72e0c6ca-1269-4e1d-9cf9-be78ec0c4584@y6g2000yqe.googlegroups.com>,
Goran  <goran.pusic@gmail.com> wrote:
>On Nov 28, 6:20 pm, Christopher <cp...@austin.rr.com> wrote:
>> If you were on a team of developers that had little C++ experience,
>> how would you go about explaining the reasoning as to why the
>> following rules should be followed? (Or why they shouldn't)
>>
>> 1) Class defintions go in their own .h (or .hpp for templates) file
>> named after the class
>
>Don't know about hpp for templates. It's *.h or *.hpp for everything
>if you ask me. If there is only one class ion the file, or if it's
>clearly the "main" class in it, then class_name.h is only natural.

Maintainability: if the general rule that each class "class_name" is
defined in class_name.h and implemented in class_name.cpp, navigating
the code is easier than if 7 different classes are defined in file1.h
and randomly implemented in file2.cpp and file3.cpp and some additonal
classes are defined and implemented entirely in file3.cpp

>> 2a) A .cpp should never contain a class definition
>
>Disagreed. There's classes that will only be used in one translation
>unit. What can one gain by making another trivial header?

I don't entirely disgree with you. but in large project, this can be a
valid policy.  

Typically, what will happen is devA decides he needs a little helper
class for his big class, he knows he only needs it here in this
specific translation unit so just define and implement it fully inside
big_class.cpp. 

Then often, devB, who is implementing another_class, needs some helper
functionality. It's fairly generic functionality so he peeks in the
generic area for a header file that might indicate that this
functionality is already available. He doesn't see anything so he
implements my_helper_class inside another_class.cpp ith functionality
almost to same as that implemented by devA previously.

Then so on for DevC, DevD ... 

If you are lucky, maybe DevE actually finds the implemention that
exists in big_class.cpp and figure out that he should reuse it rather
than duplicate the functionality.  Unfortunately, for him to reuse it,
he now has to extract first_helper out of big_class.cpp, create
first_helper.h and first_helper.cpp. 

If instead DevA wrote first_helper in its own files, any future reuse
would have been much easier.

In a previous life, I once searched through the code base of a large-ish
C project and found something like 4-5 different implementation of a
XML-quoting function, all of them defined and implemented locally.

Then there's unit testing: if your class is only defined inside a a
cpp file, it's rather difficult to unit test it.

>
>> 8) Every .cpp file should compile into a .obj file without error or
>> warning on its own.
>>    i.e In Visual Studio, you should be able to right click a .cpp in
>> the source tree and choose compile, without error or warning in the
>> output.

More important in my opinion:

For every header file the following should compile without error or
warning:

#include "the_header.h"
int main() { return 0; }

if you need to preceed #include "the_header.h" by anything, your
header file is not self contained and should be fixed.

Yannick

[toc] | [prev] | [next] | [standalone]


#11904

FromRui Maciel <rui.maciel@gmail.com>
Date2011-11-28 20:07 +0000
Message-ID<jb0pmf$fn$1@speranza.aioe.org>
In reply to#11892
Christopher wrote:

> If you were on a team of developers that had little C++ experience,
> how would you go about explaining the reasoning as to why the
> following rules should be followed? (Or why they shouldn't)
> 
> 1) Class defintions go in their own .h (or .hpp for templates) file
> named after the class
> 1a) Every class should have its own .h (or .hpp for templates) file
> 1b) A .h file should never contain class implementation (except for
> inline functions or methods)
> 
> 2) Class implementations go in their own .cpp file (except for
> templates)
> 2a) A .cpp should never contain a class definition
> 
> 3) One should not define multiple classes in a single .h file
> 3a) Nested class defintions should be avoided without good reason
> (what's good reason?)
> 
> 6) Variables should never be defined in a .h file
> 7) Globals should not be defined in a .h file
> 8) Every .cpp file should compile into a .obj file without error or
> warning on its own.
>      i.e In Visual Studio, you should be able to right click a .cpp in
> the source tree and choose compile, without error or warning in the
> output.
> ----
> 
> Sadly, I find myself having to justify these things. (of course
> someone might point out I am wrong or exceptions to the above), but
> these are things that I've always had drilled into my head throughout
> the years and have rarely come acorss other developers that didn't do
> the same. I am finding it frustrating to work on a project where 30
> classes defintions reside in the .h same .h file, a single .cpp file,
> or worse a precompiled header. There is discussion, but I have to
> explain reasoning.

Separating declarations from implementations and mandating that each class 
should be defined and implemented in separate source files are a couple of 
practices which help track what changes were made to each individual 
component and who made those changes.  With this, auditing the code becomes 
a bit simpler.

This practice also reduces the amount of potential merging conflicts any 
commit might induce.


Rui Maciel

[toc] | [prev] | [next] | [standalone]


#11905

FromGeoff <geoff@invalid.invalid>
Date2011-11-28 12:17 -0800
Message-ID<0qq7d7dttuhi1fll7hvf0gqfk5n90u29o0@4ax.com>
In reply to#11892
I disagree with your rule 6. It precludes #define.

Also, rule number 6: there is no rule 6! 
(Obligatory Monty Python reference.)

For some very interesting coding standards referenced by no less
authority than Stroustrup himself:

http://www2.research.att.com/~bs/JSF-AV-rules.pdf

via his page:
http://www2.research.att.com/~bs/C++.html

[toc] | [prev] | [next] | [standalone]


#11913

FromIan Collins <ian-news@hotmail.com>
Date2011-11-29 11:41 +1300
Message-ID<9jih16F4d0U24@mid.individual.net>
In reply to#11905
On 11/29/11 09:17 AM, Geoff wrote:
> I disagree with your rule 6. It precludes #define.

Which was "Variables should never be defined in a .h file".  Context is 
good.


Why would you be using #define for variables in C++?

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#11956

Fromgwowen <gwowen@gmail.com>
Date2011-11-29 07:37 -0800
Message-ID<aa2bf9ff-f6c5-4de7-a9ac-3e5c29c3668a@q16g2000yqn.googlegroups.com>
In reply to#11913
On Nov 28, 10:41 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 11/29/11 09:17 AM, Geoff wrote:
>
> > I disagree with your rule 6. It precludes #define.
>
> Which was "Variables should never be defined in a .h file".  Context is
> good.
>
> Why would you be using #define for variables in C++?

In a header, you may want some C/C++ cross compatibility and the C
definition of what counts as a compile-time constant can make it the
least-unpleasant way to define a constant.

romanes.h:
------------------------
const size_t NROMANS = 512;
#define HOWMANYROMANS 512

romanes.c
-----------------
static int[NFOO]; /* D'oh! Won't compile as C */
static int[HOWMANYROMANS]; /* Will compile as C*/

[toc] | [prev] | [next] | [standalone]


#11934

FromGoran <goran.pusic@gmail.com>
Date2011-11-29 00:08 -0800
Message-ID<f48446b8-ddb7-4e35-bad6-04f129a21d80@u5g2000vbd.googlegroups.com>
In reply to#11905
On Nov 28, 9:17 pm, Geoff <ge...@invalid.invalid> wrote:
> I disagree with your rule 6. It precludes #define.
>
> Also, rule number 6: there is no rule 6!
> (Obligatory Monty Python reference.)
>
> For some very interesting coding standards referenced by no less
> authority than Stroustrup himself:
>
> http://www2.research.att.com/~bs/JSF-AV-rules.pdf
>
> via his page:http://www2.research.att.com/~bs/C++.html

+1. This is "C++ for embedded systems bible" IMHO.

Goran.

[toc] | [prev] | [next] | [standalone]


#11957

FromDaniel <danielaparker@gmail.com>
Date2011-11-29 08:31 -0800
Message-ID<0872fe37-4a78-4947-b637-8363b51d270c@g21g2000yqc.googlegroups.com>
In reply to#11905
On Nov 28, 3:17 pm, Geoff <ge...@invalid.invalid> wrote:
> For some very interesting coding standards referenced by no less
> authority than Stroustrup himself:
>
> http://www2.research.att.com/~bs/JSF-AV-rules.pdf
>
Interesting to see the recommended naming conventions,

Example_class_name

RGB_colors

example_function_name

Underscores don't seem to be that popular though, more likely to be
seen are ExampleClassName, RGBColors or RgbColors, and
exampleFunctionName.

Daniel

[toc] | [prev] | [next] | [standalone]


#11962

Fromralph <nt_consulting64@yahoo.net>
Date2011-11-29 14:49 -0600
Message-ID<71gad7p4tapl8t5n3g43dj55lrka5i2kco@4ax.com>
In reply to#11957
On Tue, 29 Nov 2011 08:31:55 -0800 (PST), Daniel
<danielaparker@gmail.com> wrote:

>On Nov 28, 3:17 pm, Geoff <ge...@invalid.invalid> wrote:
>> For some very interesting coding standards referenced by no less
>> authority than Stroustrup himself:
>>
>> http://www2.research.att.com/~bs/JSF-AV-rules.pdf
>>
>Interesting to see the recommended naming conventions,
>
>Example_class_name
>
>RGB_colors
>
>example_function_name
>
>Underscores don't seem to be that popular though, more likely to be
>seen are ExampleClassName, RGBColors or RgbColors, and
>exampleFunctionName.
>
>Daniel

What you are describing is called Camel Case or Camelback. Most
historians trace its use as a direct migration from using inner
underscores as a delimiter to using uppercase to separate words.
Mostly because it saved space and yet still provides readability.

Underscores were popular in the early days of C and C++, and it is
just that popularity that has led to discouraging their use. So many
libraries and implementations used underscores - collisions were
inevitable.

ANSI now forbids them in some contexts.

However, it might be useful to remember before posting that there are
three subjects that are best avoided in this newsgroup:
1) Favorite Editors,
2) Indent Styles,
3) and Naming Conventions

-ralph <bg>
[*Comments should receive honorable mention.]

[toc] | [prev] | [next] | [standalone]


#11963

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2011-11-30 00:21 +0000
Message-ID<slrnjdatok.1bk.grahn+nntp@frailea.sa.invalid>
In reply to#11962
On Tue, 2011-11-29, ralph wrote:
> On Tue, 29 Nov 2011 08:31:55 -0800 (PST), Daniel
> <danielaparker@gmail.com> wrote:
>
>>On Nov 28, 3:17 pm, Geoff <ge...@invalid.invalid> wrote:
>>> For some very interesting coding standards referenced by no less
>>> authority than Stroustrup himself:
>>>
>>> http://www2.research.att.com/~bs/JSF-AV-rules.pdf
>>>
>>Interesting to see the recommended naming conventions,
>>
>>Example_class_name
>>
>>RGB_colors
>>
>>example_function_name
>>
>>Underscores don't seem to be that popular though, more likely to be
>>seen are ExampleClassName, RGBColors or RgbColors, and
>>exampleFunctionName.
>>
>>Daniel
>
> What you are describing is called Camel Case or Camelback. Most
> historians trace its use as a direct migration from using inner
> underscores as a delimiter to using uppercase to separate words.
> Mostly because it saved space and yet still provides readability.
>
> Underscores were popular in the early days of C and C++, and it is
> just that popularity that has led to discouraging their use.

Underscores is still my main style, for function and variable names.
It's also the style for the Linux kernel and many Unix utilities.

I suspect under_score is simply an old Unix convention. Most other
OSes seem to use some CamelCase variant. (Happily, none that I know of
uses ALL_UPPERCASE as the main style.)

> So many
> libraries and implementations used underscores - collisions were
> inevitable.

That doesn't make sense -- you cannot invent a new naming convention
for each library! Prefixes is the way it's done, pre-namespaces at
least.

> ANSI now forbids them in some contexts.
>
> However, it might be useful to remember before posting that there are
> three subjects that are best avoided in this newsgroup:
> 1) Favorite Editors,
> 2) Indent Styles,
> 3) and Naming Conventions

Yes, but we're ok as long as there's no advocacy involved.

/Jorgen

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

[toc] | [prev] | [next] | [standalone]


#11907

FromAndy Champ <no.way@nospam.invalid>
Date2011-11-28 21:30 +0000
Message-ID<yPednYfPns34YE7TnZ2dnUVZ8iWdnZ2d@eclipse.net.uk>
In reply to#11892
On 28/11/2011 17:20, Christopher wrote:
> If you were on a team of developers that had little C++ experience,
> how would you go about explaining the reasoning as to why the
> following rules should be followed? (Or why they shouldn't)

"Because I've been doing it for years and it works.  Here are a couple 
of standard texts that advise something similar.  You might have 
occasions for breaking these ***guidelines*** - if you do, talk to me 
first".  But that said...

>
> 1) Class defintions go in their own .h (or .hpp for templates) file
> named after the class

We never use .hpp files.

> 1a) Every class should have its own .h (or .hpp for templates) file

This is a guideline only.  As an example - I've recently added a new .h 
file to our code which contains 4 pure virtual class definitions - 
they'd be interfaces if C++ supported such a thing.  They're to support 
a similar function in 4 other classes.  The reason they are there is 
that the 4 ought to look similar - they are handling error cases as we 
serialise a data set into an object model.  Each one has a method or two 
similar to

virtual variabletype GetAbsentothertype(const unsigned index) = 0;

where variabletype & othertype differ. I realised that different people 
were implementing "GetAbsent", "CreateAbsent", "FindAbsent"... and this 
keeps the unrelated functions looking similar.  It has no other purpose.

> 1b) A .h file should never contain class implementation (except for
> inline functions or methods)

As we never use .hpp files...

>
> 2) Class implementations go in their own .cpp file (except for
> templates)
> 2a) A .cpp should never contain a class definition

Locally used helper classes can happily be hidden away inside a .cpp file.

>
> 3) One should not define multiple classes in a single .h file
> 3a) Nested class defintions should be avoided without good reason
> (what's good reason?)

An example: A class is a specialised container for a collection of some 
other type.  There's a helper for the sort order that's used for nothing 
else.  Hiding it inside the class where it's obvious that it is 
associated can make sense (sometimes!) and reduces the pollution of your 
namespace.

>
> 6) Variables should never be defined in a .h file

What do you mean by variables?  Obviously not class members...

> 7) Globals should not be defined in a .h file

... and apparently not globals.  But let me stretch that rule.

"Globals should not be".
If they must, then they should normally
"be defined in a .h file".

> 8) Every .cpp file should compile into a .obj file without error or
> warning on its own.
>       i.e In Visual Studio, you should be able to right click a .cpp in
> the source tree and choose compile, without error or warning in the
> output.

Be careful on warnings.  Visual Studio will throw warnings at level 4 on 
the standard Microsoft headers.  We have a few that come out on level 3 
that we can't get rid of without disabling the warning globally.

But on the errors, agree 100%.

<snip>

As someone said upthread "There is no rule 6".  Look on them as 
guidelines, which can be broken occasionally.  They are here to help, 
not hinder.

Andy

[toc] | [prev] | [next] | [standalone]


#11920

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2011-11-28 18:05 -0600
Message-ID<Xns9FAC154E73B4Dmyfirstnameosapriee@216.196.109.131>
In reply to#11892
Christopher <cpisz@austin.rr.com> wrote in news:d30834a8-3bf4-49a4-b1eb-
b66aef965475@i8g2000vbh.googlegroups.com:

> 8) Every .cpp file should compile into a .obj file without error or
> warning on its own.
>      i.e In Visual Studio, you should be able to right click a .cpp in
> the source tree and choose compile, without error or warning in the
> output.

This goes against the practice of putting platform-specific code in 
separate .cpp files (which can share a common cross-platform .h file). One 
cannot and should not be able to compile Linux-specific .cpp-s on Windows, 
or vice versa. 

Including all these Linux-specific .cpp-s in the Visual Studio projects is 
a good idea though as then they become easily greppable (Shift-Ctrl-F). 
They should however be marked as "Exclude from build". I have never tried 
if right-click-compile works on such a file... nope, Compile is grayed out. 
That's how it should be.

Also, avoiding all warnings at any cost might be counter-productive. The 
unimportant warnings should be fixed or suppressed only if they start to 
hinder finding other (important) errors or warnings in the compiler output.

cheers
Paavo

[toc] | [prev] | [next] | [standalone]


#11921

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2011-11-28 18:27 -0600
Message-ID<Xns9FAC18F41BB6Fmyfirstnameosapriee@216.196.109.131>
In reply to#11892
Christopher <cpisz@austin.rr.com> wrote in news:d30834a8-3bf4-49a4-b1eb-
b66aef965475@i8g2000vbh.googlegroups.com:

> the same. I am finding it frustrating to work on a project where 30
> classes defintions reside in the .h same .h file, a single .cpp file,
> or worse a precompiled header. 

There are always exceptions, so such rules cannot be made absolute. The 
first rule should be that any rule can be broken if justified. 

The one-class-per-cpp rule is good so far as you have few classes. If you 
have hundreds or thousands of them, then looking them up in the file 
listings starts to be cumbersome. Searching-grepping is more scalable, 
but then it will not be so important any more if the classes are in 
separate files or not. 

For example, in our codebase there are many C++ classes which define 
modules (essentially commands) for a scripting language. These classes 
are registered by the scripting language interpreter, otherwise they are 
not needed for any other code, so there is no reason to put the class 
definitions in the header file. Also, the classes are typically quite 
short, which would make it cumbersome to put each class in a separate 
.cpp file. Besides, it would make the registration mechanism much more 
awkward. So there are a lot of such classes in the same .cpp file (as 
much as 96, 88 and 63 in some .cpp files). Yeah, maybe this is a bit too 
much, but I do not believe that putting all these into hundreds of 
separate .cpp files would make anything better.

Cheers
Paavo

[toc] | [prev] | [next] | [standalone]


#11933

FromJuha Nieminen <nospam@thanks.invalid>
Date2011-11-29 07:55 +0000
Message-ID<4ed48fde$0$2782$7b1e8fa0@news.nbl.fi>
In reply to#11892
Christopher <cpisz@austin.rr.com> wrote:
> 1) Class defintions go in their own .h (or .hpp for templates) file
> named after the class

  I never use ".h" as a file name extension for C++ headers for a rather
obvious reason: It's not C code and I want to distinguish C code from C++
code unambiguously. Also, I don't see why headers containing templated
code should be named differently from headers that don't.

  From unix I am accustomed to using .cc and .hh extensions, but that's
another story.

> 1a) Every class should have its own .h (or .hpp for templates) file

  You are polluting the global namespace this way for classes that could
well be compilation-unit-local. Such classes should go into a nameless
namespace, which is incompatible with a public header file. (Ok,
technically speaking you can put a nameless namespace in a header file
because, after all, it's just C++ code like everything else, but the
advantage of doing this is dubious. You will only be including it in
the compilation unit where it's used, and including it anywhere else
would be useless, as it would only define an unimplemented local class.)

  You might have learned otherwise, but I have learned that public interfaces
should be as minimal as possible, and polluting the global namespace with
local types is not good design.

> 1b) A .h file should never contain class implementation (except for
> inline functions or methods)

  That's a null statement. If a header file contains implementations,
they will be inline by necessity (else you'll get linker errors if the
header is included more than once), so that rule isn't really saying
anything.

  Perhaps if you had said: "A header file should contain inline function
implementations only if there's a very good reason for them. Otherwise
they should go to the correspondent compilation unit."

> 2) Class implementations go in their own .cpp file (except for
> templates)

  Technically speaking templates can be declared in a header file and
implemented in a compilation unit even in cases where the template is
used somewhere else besides that compilation unit (yes, even without
support for export; it can be done with explicit template instantiation),
but that's not a usual circumstance. But I digress.

> 2a) A .cpp should never contain a class definition

  Why not? If a class is used only in that one compilation unit, and
especially if it's small, what's the problem?

  Think about this: What would be the difference between a private inner
class and a class local to the compilation unit (ie. in a nameless namespace),
except for scope? Would the former be ok but not the latter? Why?
(The testability argument doesn't hold because you cannot test a private
inner class from the outside.)

  (And please don't tell me you oppose private inner classes too.)

> 3) One should not define multiple classes in a single .h file

  If two classes are relatively small and strongly related to one other,
why not? A typical example would be a template class and a specialization
for a specific template type. If you put them in separate header files, you
would have a small problem in what to include. There are many non-templated
examples as well.

> 3a) Nested class defintions should be avoided without good reason
> (what's good reason?)

  I don't see why inner classes "should be avoided".

  In general class design should be as simple as possible. That includes,
among many other things, minimizing the amount of inner classes. However,
there's nothing special about them in particular that should be avoided.

  Iterators are good examples of public inner classes. Why should they be
avoided? And if some private implementation of the class needs a private
class, then why not? (In fact, sometimes trying to religiously avoid inner
classes can make your code much more complicated and harder to manage.)

> 6) Variables should never be defined in a .h file

  There are some situations where extern variables are justified. Although
even in those cases they should usually be declared inside a namespace to
minimize global namespace pollution. (std::cout would be an example.)

> 7) Globals should not be defined in a .h file

  Well, duh. You'll get a linker error if you do. (At least if you include
the header in more than one place.)

> 8) Every .cpp file should compile into a .obj file without error or
> warning on its own.

  Hmm, is there any other way? Or what do you mean "on its own"? I don't
even know of any other way of compiling a C++ program than one compilation
unit at a time.

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c++


csiph-web