Reputation: 111
I recently had a problem where I was writing a library with lots of function definitions in the .h files and as the library got more interdependent I started running into lots of multiple definitions of functions errors so in order to reduce refactoring I declared all my functions as inline, but I'm wondering why I didn't have to change anything for the classes defined in the same .h files? Shouldn't the classes also be getting duplicated?
Upvotes: 0
Views: 111
Reputation: 26256
You can put functions also in .h
files, but also function definitions only; not declarations, unless they are template functions. So basically it's the same rules with classes, except that with classes, if you do them the quick-and-dirty way, you put everything inside the class itself and you combine definitions with declarations, which is not really good practice.
So:
This goes to an .h file:
int DoSomething(double x, double y);
And this goes to a .cpp file
int DoSomething(double x, double y)
{
return static_cast<int>(x+y);
}
While this (if you care about templates, otherwise just ignore this), can only go to an .h file:
template <typename T>
int DoSomething(T x, T y)
{
return static_cast<int>(x+y);
}
This whole thing is not for fun. There's a very good reason for it. The reason is that .h
files represent an API, while .cpp
files represent an implementation. Ideally, an API is something you plan ahead and never changes. On the other hand, an implementation can be updated to fix bugs, for example.
Also cpp files can be compiled to a dynamic link library (dll) or shared library, which can be then updated without modifying the API. So you can use the same API in your program by including some .h
file, and link it to a different implementations, if you like.
And if you ask: Why templates can only be in .h
files, it's because compiled stuff must be with a predefined type. You can't compile something without knowing what type it is.
The story can go for pages... but I think this suffices to explain the basics (I hope).
Upvotes: 1
Reputation: 385144
You can declare variables, functions and classes in a header, and include that header into multiple translation units, and have no problems. But what you've been doing is defining functions, which is different.
Classes are special in that you may define them in multiple translation units, as long as the contents of each copy are precisely identical — this special rule is important because otherwise your classes wouldn't be very useful; a class that has only been declared can't be immediately used for very much, whereas a function that has only been declared can be immediately used for pretty much anything.
That's just a consequence of the different nature of the two kinds of things.
// Declarations
extern int x; // variable
void foo(); // function
class T; // class
// Definitions
int x; // variable
void foo() {} // function
class T {}; // class
Upvotes: 2