For example you have such situation:
1)Header file with some class definition that contain some member function (def.h).
2)That header is included into .cpp files with the same name that resides in a separate folders.
3)That .cpp files impements same function from def.h but in different way.
3)Then we include that header into some main.cpp and call function with multiple impementation and compile that whole project.
Question: will it compile without errors? What function implementation will be chosen?
Defining a function in two separate places violates One Definition Rule.
One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.
To have well-defined behavior, you should either:
Link just one of the definitions in the final program
Use overloads instead
Use polymorphism/inheritance instead
Related
I am trying to a make plugin system which will have a header file for all plugins to include. In that header the version of the plugin system is defined in a #define like so:
PluginHeader.hpp:
#define PLUGIN_SYSTEM_VERSION "00.001"
class PluginSystem
{
public:
string GetSystemVersion(){return PLUGIN_SYSTEM_VERSION; }
void MyPluginDoStuff(){...}
}
I compile my plugin with this header in a dll and export it. Afterwards, i import it in the main application and i change the value of the #define in the calling application to be "00.002". If i call the method GetSystemVersion in the dll, then i am getting the new value "00.002".
Is this the expected behavior? How can i make the dll keep its defined value?
It is neither expected nor unexpected behaviour. Your program has undefined behaviour, so any outcome (whether it seems "right" or not) is possible.
Your member function PluginSystem::GetSystemVersion() is defined (implemented) within its class definition, so is implicitly inline.
The problem is, by having different definitions of the macro PLUGIN_SYSTEM_VERSION in different compilation units (e.g. in your DLL and in a separate source file that includes your header), you cause your program to have multiple definitions of PluginSystem::GetSystemVersion() (and, in fact, the whole class PluginSystem) in your program. If those definitions aren't exactly the same, you're breaking the one-definition rule. Which for an inlined function (and for a class) means that all definitions seen by different source files must be identical.
Breaking the one-definition rule means your program has undefined behaviour. Seeing different versions of an inline function being called in different compilation units (e.g. the DLL version called in some situations but not others) is one possible symptom of that.
If you want to have the function in the DLL, then
Change the class definition so that the function is not inline within the class definition, and ensure that class definition is used consistently everywhere (both in all source files for your program, and in all source files for the DLL) - for example, by including the same header everywhere it is needed;
In exactly one source file, for the DLL, include exactly ONE definition of the function outside the class definition.
Although not technically necessary, I'd encourage you to avoid using macros (other than include guards) in the header (or, even, using a macro for it at all - there are alternatives). If you must have a macro PLUGIN_SYSTEM_VERSION, define it locally to the single source file that defines PluginSystem::GetSystemVersion(). That avoids the possibility of confusing yourself (and increasing chances of getting unexpected behaviours) by having different incantations of PLUGIN_SYSTEM_VERSION (and code affected by it) in different parts of your program.
According to Why can't I multi-declare a class
class A; is a declaration while
class A { ... } is a definition
Typically, in header files, we define the class and we implement its member functions in the .cpp. But wouldn't defining classes in the header file violate the One Definition Rule?
According to https://www.learncpp.com/cpp-tutorial/89-class-code-and-header-files/
Doesn’t defining a class in a header file violate the one-definition rule?
It shouldn’t. If your header file has proper header guards, it
shouldn’t be possible to include the class definition more than once
into the same file.
Types (which include classes), are exempt from the
part of the one-definition rule that says you can only have one
definition per program. Therefore, there isn’t an issue #including
class definitions into multiple code files (if there was, classes
wouldn’t be of much use).
While the first part is obviously true, header guards will prevent multiple definitions in the same file, but I am confused about the second part of the answer that addresses my question.
If a header file has a definition of a class, for example ThisClass, and that header file is included in two other files for example a.cpp and b.cpp. Why wouldn't it violate the One Definition Rule? If a ThisClass object is created in either file, which definition would be called?
If a header file has a definition of a class, for example ThisClass, and that header file is included in two other files for example a.cpp and b.cpp. Why wouldn't it violate the One Definition Rule?
Because, as you quoted, the one definition rule specifically allows for this.
How can it? Read on…
If a ThisClass object is created in either file, which definition would be called?
It doesn't matter, because the definitions are required to be absolutely, lexically identical.
If they're not, your program has undefined behaviour and you can expect all manner of weirdness to ensue.
Based on what I'm reading, it might be important to use Wikipedia's brief explanation of what the One Definition Rule actually is:
The One Definition Rule (ODR) is an important rule of the C++ programming language that prescribes that objects and non-inline functions cannot have more than one definition in the entire program and template and types cannot have more than one definition by translation unit.
This means that when the program is compiled, there can be one, and only one definition of a function or object. This might be confusing, however a class or type shouldn't be thought of as objects, they're really just blueprints for an object.
In your question, I think there's a misunderstanding of what #include does and how the ODR applies to classes. When the program is compiling, the .cpp files look to their #include'd class definitions as a way to link together, that is, the class.h blueprint must know where to look when calling it's member functions. Having multiple #include's of the same class.h is not the same as having multiple definitions of class.h, and thus, it cannot violate the One Definition Rule.
It is okay to have a class defined in a header file because the compiler treats the functions declared in the class in such a case as an inline functions.
So there are two options to happen when you call this class functions:
Or it wiil inline the function calls and in such a case there is no problem at all of multiple definition.
Or it wont inline them and in such a case he will create the symbols related to the functions as weak symbols. Then the linker will choose one of the symbols to be the symbol representing the function.
Of course if there will be different defintions in two or more cpp files there will be undefined behaviour.
I've used MATCHER_P from gmock to create some matchers in different *.cpp test files. They happened to be defined in the same namespace and had the same name. When running the tests, I've got a segfault, because a test from fooTest.cpp used a matcher from barTest.cpp, even though a matcher with the same name was declared in fooTest.cpp and barTest.cpp was obvoiusly not included.
What is going on here? Why does the test from fooTest.cpp even see the matcher declared in barTest.cpp? Shouldn't it be confined to the scope of the file that it's declared in? And if not why am I not getting a compilation error that says something about an "ambiguous call?"
The compiler is not required to diagnose violations of the One Definition Rule, so your program exhibits undefined behavior.
From [basic.def.odr]
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in
that program outside of a discarded statement; no diagnostic required.
IIRC some linkers can warn about these things, but again there's no requirement.
Best to simply move one of those functions into a different namespace.
Using my crystal ball, your problem is that you have to identically named inline methods or functions. Functions defined in the body of a class are implicitly inline.
When you have two different inline functions with the same name, the linker silently discards all but one of them. Such names include the names of the class they are part of.
If the implementation of one or the other is different, this leads to problems. One classic problem is inlined non-trivial zero argument constructors for objects of different size; one of them is discarded, and now you are clearing the wrong amount of memory for the wrong class.
This could be laid at the feet of a one definition rule violation -- the very existence of your two classes is a ODR violation and makes your program ill formed, no diagnostic required.
But knowing the step that actually caused your program to keel over is useful.
The fix this this is to always define everything in a cpp file within an anonymous namespace. Anything that defines a symbol in a header file should fully qualify it. Now no definitions in one cpp file can collide with definitions in another accidentally.
I'm working my way through a C++ tutorial, and in one of the articles on the preprocessor/header files the author creates 2 'header files' (not the technical term, of course), example.h and example.cpp. In example.h he puts the forward declarations for the functions and the header guard, and in example.cpp the actual body of the functions. Why is this? I tried putting the body of the function in the example.h file and it worked just fine, so why does he put it separately? Is it customary, or does it pose problems in bigger problems? Or what?
Can someone please enlighten me on this...
C++ has a rule called the one-definition rule that says that every function needs to be defined once and only once (there are a few exceptions to this rule, but we'll ignore them for now.) The function prototype typically included in a header file is a declaration saying that the function exists, and the implementation in the .cpp file is the definition giving the code for the function.
If you put the definition of the function in a header file and then include the header file in multiple places, you'll get linker errors because you're breaking the one definition rule - each .cpp file that's compiled will have its own copy of the definition of the function. On the other hand, if you just put the declaration in the header and then put the definition in a single source file, then there's only one definition and nothing will break.
There are a few exceptions for the one definition rule. First, all inline functions are exempt from ODR, so you could potentially put function definitions in a header file if you mark all the functions inline, though this is generally not considered a good idea for all but the smallest functions. Second, template functions are exempt from the ODR, which (among other things) is one of the reasons you see template functions defined in headers.
Put the function body in example.h. Then, when you write a second .cpp file that also includes example.h, and link it with example.cpp, then you'll get a linker error. The linker will see 2 definitions of the function in example.h.
Becouse in the header file you only declare functions that is really important when you want to use a custom linking configuration. For example if a function is defined in a file object and is used in an another object the linker must have the same reference for this function to link the two different files.
After reading this question I thought I understood everything, but then I saw this file from a popular header-only library.
The library uses the #ifndef line, but the SO question points out that this is NOT adequate protection against multiple definition errors in multiple TUs.
So one of the following must be true:
It is possible to avoid multiple definition linker errors in ways other than described in the SO question. Perhaps the library is using techniques not mentioned in to the other SO question that are worthy of additional explanation.
The library assumes you won't include its header files in more than translation unit -- this seems fragile since a robust library shouldn't make this assumption on its users.
I'd appreciate having some light shed on this seemingly simple curiosity.
A header that causes linking problems when included in multiple translation units is one that will (attempt to) define some object (not just, for an obvious example, a type) in each source file where it's included.
For example, if you had something like: int f = 0; in a header, then each source file into which it was included would attempt to define f, and when you tried to link the object files together you'd get a complaint about multiple definitions of f.
The "technique" used in this header is simple: it doesn't attempt to define any actual objects. Rather, it includes some typedefs, and the definition of one fairly large class--but not any instances of that class or any instance of anything else either. That class includes a number of member functions, but they're all defined inside the function definition, which implicitly defines them as inline functions (so defining separately in each translation unit in which they're used is not only allowed, but required).
In short, the header only defines types, not objects, so there's nothing there to cause linker collisions when it's included in multiple source files that are linked together.
If the header defines items, as opposed to just declaring them, then it's possible to include it in more than one translation unit (i.e. cpp file) and have multiple definitions and hence linker errors.
I've used boost's unit test framework which is header only. I include a specified header in only one of my own cpp files to get my project to compile. But I include other unit test headers in other cpp files which presumably use the items that are defined in the specified header.
Headers only include libraries like Boost C++ Libraries use (mostly) stand-alone templates and as so are compiled at compile-time and don't require any linkage to binary libraries (that would need separate compilation). One designed to never need linkage is the great Catch
Templates are a special case in C++ regarding multiple definitions, as long as they're the same. See the "One Definition Rule" section of the C++ standard:
There can be more than one definition of a class type (Clause 9),
enumeration type (7.2), inline function with external linkage (7.1.2),
class template (Clause 14), non-static function template (14.5.6),
static data member of a class template (14.5.1.3), member function of
a class template (14.5.1.1), or template specialization for which some
template parameters are not specified (14.7, 14.5.5) in a program
provided that each definition appears in a different translation unit,
and provided the definitions satisfy the following requirements. ....
This is then followed by a list of conditions that make sure the template definitions are identical across translation units.
This specific quote is from the 2014 working draft, section 3.2 ("One Definition Rule"), subsection 6.
This header file can indeed be included in difference source files without causing "multiple symbol definition" errors.
This happens because it is fine to have multiple identically named symbols in different object files as long as these symbols are either weak or local.
Let's take a closer look at the header file. It (potentially) defines several objects like this helper:
static int const helper[] = {0,7,8,13};
Each translation unit that includes this header file will have this helper in it. However, there will be no "multiple symbol definition" errors, since helper is static and thus has internal linkage. The symbols created for helpers will be local and linker will just happily put them all in the resulting executable.
The header file also defines a class template connection. But it is also okay. Class templates can be defined multiple times in different translation units.
In fact, even regular class types can be defined multiple times (I've noticed that you've asked about this in the comments). Symbols created for member functions are usually weak symbols. Once again, weak symbols don't cause "multiple symbol definition" errors, because they can be redefined. Linker will just keep redefining weak symbols with names he has already seen until there will be just one symbol per member function left.
There are also other cases, where certain things (like inline functions and enumerations) can be defined several times in different translation units (see §3.2). And mechanisms of achieving this can be different (see class templates and inline functions). But the general rule is not to place stuff with global linkage in header files. As long as you follow this rule, you're really unlikely to stumble upon multiple symbol definitions problems.
And yes, include guards have nothing to do with this.