Reputation: 4663
An example:
//a.h
// no include guards
class A {};
If I include this header twice in one translation unit (one cpp file) I'll get a linker error, it's ok. But it's also ok if I include it in 2 different translation units, right?
Now consider a global function:
// b.h
// no include guards
void foo() {}
Not only it's not allowed to include it twice to the same unit, but also it's not allowed to include it for the second time in any other translation unit. Why?
Upvotes: 2
Views: 502
Reputation: 149085
You make confusion between declaration and definition. You can have as many identical declarations in your translation units. So if foo
is a function returning and int and taking one int and one string, the declaration int foo(int i, std::string s);
can be repeated as many times as you want. It should exist in every translation unit (cpp file) before first use. You can also declare classes. A forward declaration for class A would be : class A;
with nothing more and can be repeated in one translation unit.
Definitions for functions are only allowed once in the whole program. The definition of foo
would be something like:
int foo(int i, std::string s) {
return i + s.size();
}
The full declaration of class A could be :
class A {
int a;
std::string s;
public:
A(int a):s("") { this->a = a;} // this constructor is declared and defined inline
int bar(int a); // this method is only declared here, will be defined elsewhere
...
};
This can only occur once in each translation unit.
The definition for method bar
(which what only declared in class declaration) could be:
int A::bar(int i) {
return i + a;
}
This definition can only occur once in the whole program.
Once that has been said the rules are:
(*) common usage is to include both only once in each translation unit using them by using include guards.
The why of the above: first it is the law and we all must obey. But it is easy to the compiler to see in function declaration and forward class declaration are identical, so it is easy to allow them multiple times in one single translation unit. And they do not generate code by themselves so the linker does not care for them.
Function declaration can generate code. So they must occur only once in each translation unit. As they are indeed declaration they can occur in any translation unit, and the linker will keep ony one version of the generated code. Definitions actually generate code, and they have no good reason to be repeated in a program. So the linker can throw an error if same function or method is defined more than once in one program.
Upvotes: 1
Reputation: 27153
inline
will allow the same function to be defined in multiple translation units.
inline
void foo() {}
But it's up to you to ensure you provide the same definition in all case - if they are different you will get undefined behaviour.
Alternatively, instead of defining such a function in a header file, you could instead just declare it in the header file with extern
:
foo.hh:
extern void foo();
and provide a (non-inline
) definition in one translation unit (.cc file).
Template functions are implicitly inline
I believe.
Upvotes: 1
Reputation: 25599
Declaring types is allowed in multiple translation units (or else header files wouldn't work), and you can define static and inline functions also, but (simplifying) you can't define anything with "external linkage" multiple times.
If you did, which copy would you like the linker to choose?
C++ has the ODR: One Definition Rule. Basically, it says that you can duplicate the same definition in multiple places, but they have to match, or else undefined behaviour will follow.
(The less-simplified version of what I wrote above is that the linker has clever means to unify C++isms that inevitably get generated multiple times (templates, constructors, etc.): so-called "COMDAT" sections, but these don't apply to ordinary functions.)
If you want to get really technical, then you can explore "weak" linkage. Basically, you can say that the linker should use this definition unless another, strong one is available (i.e. one without the "weak" attribute). This is useful when you have optional features that you want to enable when they're available, but is not of general interest.
Another interesting problem in this space is shared libraries; sometimes, for performance or dependency reasons, the library will have a private copy of a function linked into it. This can result in different parts of your program using different copies of the same function, possibly with different capabilities, bugs etc. It's particularly troublesome when that function has static data that you wanted shared.
Of course, with shared libraries you also have the possibility of conflicting function names, but that's a violation of the ODR, and a bug.
Upvotes: 2
Reputation: 8141
That's a natural result of the compilation and linking process of C++ files.
When you compile translation units into object files, each external function is referenced by a relocation entry. When the linker links everything together, it tries to fill those relocation stubs with the actual addresses of the real functions.
Now, let's say file A.o defines foo()
, i.e. it supplies its actual code. Now say B.o needs a function foo()
. Then we tell the linker to link A.o and B.o together into an executable or library. Herein the linker wants to fill the gap, namely the relocation, in B.o. So when it sees B.o is looking for foo()
, and that A.o supplies it, and it puts the final address of foo()
in A.o inside B.o's calling code.
Now, let's say we told the linker to link together A.o, B.o and C.o. And let's say C.o, for some reason, also supplied a definition of foo()
, for example because it included a header that defined it, which A.o also included. Now the linker wants to fill the foo()
stub in B.o. Which one should it choose? The first? The second? How does it choose? This can lead to trouble if you're not careful.
That's why, by default, major linkers forbid multiple definitions of the same functions. Usually, you can enable it with a flag. But more often than not, it signals either an immediate error or a future headache.
Upvotes: 1
Reputation: 25623
If I'll include this header twice in one translation unit (one cpp file) I'll get a linker error
I believe you get a compile error not a linker error. I can see no code which should be generated so the linker sees nothing which it can complain about.
void foo{}
I believe you mean void foo(){}
!
C++ uses the "one definition rule". That's simply a definition and from the users view, it makes no sense to get definitions two times, maybe with different semantic. That's simply the language and it is a simple way to get rid of multiple different definitions in one program.
Why the originator decided to use ODR can not be given here. Maybe Bjarne reads here and can give you a more detailed answer :-)
Upvotes: 3