Classes in separate files

I'm migrating to C++ from Java, and I like how in Java each class gets it's own file. I'm trying to go that with C++, but I'm having no luck. I have a few questions regarding the process.

1) Is this even a good idea? I do not know the C++ conventions on classes. Do people tend to place them in separate files, like in Java?

2) .cpp or .h? As it stands, I have a class in a .cpp file and I'm trying to include it into another .cpp file that has the main function. Should it be in a .cpp file, or a .h file? What is each file type used for?

3) Am I including correctly? As I mentioned, I'm attempting to include a .cpp with my class in it into another .cpp file. I'm using the line #include "TestClass.cpp" for this. When I do that, I get the following errors:

1
2
3
4
5
6
7
obj\Debug\TestClass.o||In function `TestClass':|
C:\Users\Cyle\codeblocks_projects\Classes_And_Objects\TestClass.cpp|20|multiple definition of `TestClass::TestClass(std::string, int)'|
obj\Debug\main.o:C:\Users\Cyle\codeblocks_projects\Classes_And_Objects\TestClass.cpp|20|first defined here|
obj\Debug\TestClass.o||In function `TestClass':|
C:\Users\Cyle\codeblocks_projects\Classes_And_Objects\TestClass.cpp|20|multiple definition of `TestClass::TestClass(std::string, int)'|
obj\Debug\main.o:C:\Users\Cyle\codeblocks_projects\Classes_And_Objects\TestClass.cpp|20|first defined here|
||=== Build finished: 4 errors, 0 warnings ===|


I am using Code::Blocks as my IDE.
1) It makes sense to keep things logically separated by files. However there is no reason in C++ to adhere to a strict, one class per file regime. Sometimes that may make sense but not by any means always. I personally like to keep my header files as "fine grained" as logically possible.

2) Put class declarations in .h and put the implementation in .cpp. In java they go in the same file but in C++ that can be separated.

3) Only include the .h files, that is what they are for. The .h files are the description of the functionality in the .cpp files. So the compiler only needs to see the .h when compiling code that requires that functionality.
Last edited on
Disregard this post. I figured it out on my own. Works fine now.

Thank you for your response =)
Last edited on
Basically:

Put in the header:
- The class body
- Any functions you want inlined (implict or explicit)

Put in the cpp:
- Any functions you don't want inlined

(there are exceptions to the above rules, but basically that's the jist of it)

inlined functions that exist in the cpp file will cause linker errors
non-inlined functions that exist in the h file will cause linker errors.

The reason for this is that inlined functions must be fully defined in every compilation unit (cpp file) that uses them. Whereas non-inlined functions can only be defined once across all compilation units otherwise it will appear as though the same function has multiple bodies, and the linker will get confused and not know which function you meant to call.

For a basic example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//===========================
// in the header file:

class Foo
{
  int implicitly_inlined()  // function is implicitly inlined, OK to have in the header file
  {
    return 0;
  }

  int explicitly_inlined();
  int not_inlined();
};


inline int Foo::explicitly_inlined()  // explicitly inlined (note the 'inline' keyword)
{  // OK to be in .h file
  return 0;
}

//===================================
// in the .cpp file

#include "foo.h"

int Foo::not_inlined()  // not inlined, must go in the cpp file
{
  return 0;
}



EDIT:

Here's some relevent reading that I recommend: http://cplusplus.com/forum/articles/10627/
Last edited on
Thank you for that article. It is extremely detailed and will probably come in handy when I start getting into this header stuff a lot more.

There is one last thing I don't quite understand; inline functions.

I googled and from what I read, inline functions can perform better than non-inline functions. Does that mean I should use inline functions as much as I can? Or is there more to the story, like different pros and cons.
Here's the breakdown on inline functions:

http://www.parashift.com/c++-faq-lite/inline-functions.html

Specifically, read this one:
http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.3

Long story short, "inline" does not mean "faster", it means "inline". Basically when a function is inlined the code get's copy pasted into the calling function.

Example:

1
2
3
4
5
6
7
8
9
10
int add(int a, int b)
{
  return a+b;
}

// if 'add' is inlined, then this line:
  int c = add(a,b);

// .. would be the same a this line:
  int c = a+b;  // the function call is removed and replace with the body of the function 


Inlining results in less function calls (since function calls have overhead, this can increase performance). But it also results in generally larger code (since the same function body gets expanded to several different areas of code).

On the flip side, larger code can reduce performance.


A very very general rule that has many exceptions is to inline short, small functions, but don't inline large complicated functions. But as the above link mentioned, there is no golden rule that applies to all scenarios.
Last edited on
Inlining is not interesting due to the missing function call overhead, because that makes little difference in most cases (except for really simple functions such as setters/getters).
It is interesting due to code transformations the compiler can apply when it can inline a function and various optimizations that can be applied when calling functions with partly constant parameters such as constant folding, general strength reduction, including resolving expressions for conditionals at compile time (and the resulting dead code elimination for the other case) etc.
Generally it's a good idea to inline all functions that
a) aren't changed often (a change requires recompilation for all units that include the header).
b) do not call functions declared in other "heavy" headers (to minimize header dependencies).

The compiler will then decide which functions it actually wants to inline. Whether you declare a function as inline has little or no effect on inlining decisions (but is required for global non-template functions in headers).
Last edited on
Topic archived. No new replies allowed.