Question:
Avoiding multiple definition errors in C++?
2008-04-07 17:31:53 UTC
Hello friends,

I was always under the impression that if I created a header file that contained:

#ifndef HEADER_H_
#define HEADER_H_

const char* foo = "Hello" ;

#endif

I could safely include this header in as many .cpp files as I wanted, and the preprocessor directives would prevent multiple inclusions?

I'm using g++, and getting "multiple definition" errors on foo when I use the above practice. I'm now assuming that the preprocessor is applied once per .cpp file -- meaning each file will only define up to one instance of foo, however, the linker will freak out when it goes to work.

What is the best way to handle this problem? I know I could just define foo in the .cpp file, but its a constant and I like to keep constants in the .h file. I've thought about making foo extern in the header, but then I still have to initalize it in the .cpp file -- How can I do this cleanly so that the initialization is done in the header?

Thanks!
Three answers:
Michael Safyan
2008-04-07 17:53:41 UTC
No. The preprocessor guards prevent multiple inclusion for a single compilation unit (i.e. for a single .cpp file). If you have multiple compilation units (i.e. more than one .cpp file), the definition is included once per compilation unit, which is more than once in total. This will trigger a linker error, when you try to link the various compilation units together. The problem is that a header file should never contain a definition; it should only contain declarations.





REPEAT AFTER ME:

A header file should contain declarations, only!!!



What you should put in your header file is:

extern const char* const foo;



Unlike the statement "const char* foo= ...", this does not allocate space (notice the "extern" keyword), and therefore constitutes a declaration rather than a definition.



In A SINGLE compilation unit (i.e. in just one .cpp file), write:

const char* const foo = "Hello";



This will provide the single definition that you need.





NOTE:

Using global variables like this is considered to be "bad practice." It is much better to write the following:



// Some header file

const char* getfoo();



// Some C++ file

const char* getfoo()

{

return "Hello";

}



WHY YOUR SOLUTION IS BAD PRACTICE:



Your solution is bad practice, because you clearly want to make "foo" constant; however, your code makes it possible to modify "foo". The type of "foo" should be "const char* const", not "const char*" in order to make this distinction.



In my opinion, it is best to have a function which returns the constant value, because that way it is possible for someone who does not have access to your header file to still use the constant value when dynamically linking against your code.
2016-04-06 11:26:14 UTC
Taz is correct. You must include Rectangle.h in Rectangle.cpp. Putting the constructor in the .cpp file is one choice. Another is to put it in the header file as an inline, like this: class Rectangle // Rectangle class definition { private: int width; public: Rectangle() { width=0; } void getWidth(); }; Or: class Rectangle // Rectangle class definition { private: int width; public: Rectangle() : width(0) { ; } void getWidth(); }; If a function is very simple and unlikely to ever change, it makes sense to put it in the header file. If it is complex or likely enough to change that its implementation shouldn't be considered part of the class interface, put it in the .cpp file.
2008-04-07 17:42:24 UTC
Are you using AIX 5.3?

If so, then you may never be able to get rid of those duplicate symbol warnings.



Your method of ifndef, define, ... endif is correct.

You should not be getting those duplicate symbol warnings.


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...