C++: Class Declaration and Definition Separated Inside Header Causes Duplicate Symbol

c++: class declaration and definition separated inside header causes Duplicate Symbol

Yes, it's expected behavior.

Inline functions are meant to be compiled separately into each call site so duplication is no problem. For template functions, the compiler flags them in the object file such that the linker will basically ignore duplicates, since it can be difficult to predict where the template will or will not be instantiated.

But conventional functions are expected to be defined exactly once. If you define one in a header file, it gets compiled into each translation unit that includes the header, leading to a "duplicate symbol" error at link time if you have more than one object file containing a copy of the function.

Duplicate symbols with header only implementation

inline bool operator==(const Foo& a, const Foo& b) {
..
}

Member functions are implicit inline provided they are defined inside their class. The same stuff is true for them true: If they can be put into the header without hassle, you can indeed do so.

Because the code of the function is put into the header and visible, the compiler is able to inline calls to them, that is, putting code of the function directly at the call site (not so much because you put inline before it, but more because the compiler decides that way, though. Putting inline only is a hint to the compiler regarding that). That can result in a performance improvement, because the compiler now sees where arguments match variables local to the function, and where argument doesn't alias each other - and last but not least, function frame allocation isn't needed anymore.

Avoiding duplicate symbol due to initialization of specialization in header?

You can use unnamed namespace which can make your class have internal linkage, e.g.

#ifndef A_INCLUDED
#define A_INCLUDED

#include <stdint.h>

namespace {
template <class T> class Id
{
public:
static const uint8_t id;
};
}

class S;
class T;

template<> const uint8_t Id<S>::id = 0x01;
template<> const uint8_t Id<T>::id = 0x02;

#endif

Replace this code with the contents in a.h in your example, then it will work because Id<T> in one translation unit is different from that in another translation unit due to internal linkage, thus one-definition rule is not violated.

C++ #include causing 'duplicate symbols'

You are right when you say that #include-ing is just like copy-pasting the contents at the respective position.

But if you include a file that does not just contain declarations and class definitions but also implementations in the sense of variable definitions or function/methods with a body, then you might get into troubles if...

a.) you either include the same boilerplate.cpp in several other files; this will lead to redefining the same things -> duplicate symbol errors

b.) you include the boilerplate.cpp only in one file, but the compiler treats the boilerplate.cpp file also as separate translation unit -> duplicate symbols

So avoid including .cpp-files; rather expose the functions provided by that .cpp file as function prototypes (i.e. functions without a body) in an appropriate .h-file; include only the .h-files then.

Global objects in C++ says duplicate symbols

If you really need to declare global objects in header, then try this:

// Test.h
#ifndef TEST_H
#define TEST_H

#include <iostream>
using namespace std;

class Test {

public:
Test();
~Test();
void setName(string);
string getName();

private:
string name;
};
extern Test test1, test2; // This is what I called a `global object`

#endif

Now in the implementation file (Test.cpp), define them:

// Test.cpp
Test test1, test2;
// continue your implementation of the class Test as earlier

C++ member function definition outside the class | duplicate symbols

Classes are declarations. No code is produced from a declaration. Even if you have a member function in the class, it is treated as if an inline by the compiler. Function bodies can be put in a header but should always be declared as inline. The compiler may not actually inline it, but it will treat it as a single instance for code creation.

Any time you:

void function( ) { }

Code is created for that function. If a header is included more than once the compiler is told to create the code more than once. But all functions must have unique names! So you get the duplicate error. That is why code generating lines belong in the .cpp files.

'inline' tells the compiler not to create immediate code but to create the code at the usage point.

Linker fails due to duplicate symbol

The Sales_data::combine function is defined inside the header file, but you're not making it inline so each source file including that header file defines the function.

Why is there no duplicate definition error when I define a `const int` in header file?

This is one of the differences of C and C++.

In C++ a const variable is implicitly static, i.e. only visible to the current translation unit. In C it is implicitly extern so visible to the entire program (which is also the default for the other non-const declararions in both C and C++).

This explains your observation.

Note: A const char *p declaration of a variable is not a const variable. It means it points to a const variable (i.e. *p is cannot be modified), but p itself is not const. So behavior here is different. const char * const p would be a const declaration.



Related Topics



Leave a reply



Submit