An exception to the "only one implementation" rule? - c++

While I was reading the accepted answer of this question, I had the following question:
Typically, methods are defined in header files (.hpp or whatever), and implementation in source files (.cpp or whatever).
One of the main reasons it is bad practice to ever include a "source file" (#include <source_file.cpp>) is that its methods implementation would then be duplicated, resulting in linking errors.
When one writes:
#ifndef BRITNEYSPEARS_HPP
#define BRITNEYSPEARS_HPP
class BritneySpears
{
public:
BritneySpears() {}; // Here the constructor has implementation.
};
#endif /* BRITNEYSPEARS_HPP */
He is giving the implementation of the constructor (here an "empty" implementation, but still).
But why then including this header file multiple times (aka. on different source files) will not generate a "duplicate definition" error at link time ?

Inline functions are exceptions to the "one definition rule": you are allowed to have identical implementations of them in more than one compilation unit. Functions are inline if they are declared inline or implemented inside a class definition.

Member functions with implementation inside the class definition are treated as inline functions. Inline functions are exempt from one definition rule.
Specifically when the linker sees two inline functions with the same signature it treats them as if it is the same function and just picks one of them. This can lead to really weird hard to detect problems.

Because it is an "inline" function. Inline functions can be included from headers as many times as you like and they don't cause duplicate definition linker errors.
The compiler will also try to bring them inline so, in your example above, the compiler will try and eliminate the call to the constructor completely.

Related

Is duplication of declarations still a problem in C++?

Okay so I recently learned how the compiler exactly works and what the "linker" is. From the tutorial videos I've watched I clearly saw that if I include more than once a declaration, to say:
void Log(const char* message);
I would get an error since I am declaring it more than once. But currently, as I am testing it, I've created a header file which contains that particular declaration and I've included it a couple of times in my Main compilation unit, as so:
#include "Log.h"
#include "Log.h"
I have removed the #pragma once statement, nor do I have header guards written, but my program still runs perfectly and without any problems. Since the videos are 2-3 years old, I thought maybe there has been an update, which alltogether removes the need of guards and pragmas, but I do not know for sure.
The tutorials you've seen are correct. You cannot have more than one definition of something unless you use special techniques.
In this case though you don't have a definition.
void Log(const char* message);
is a declaration and you are allowed to have multiples of those. If you change the code to
void Log(const char* message) {}
then you would have a function definition and will get an error.
I would get an error since I am declaring it more than once.
Re-declaration is generally allowed, as long as you don't mix different kinds of declarations with the same name. Following is perfectly legal C++, and always has been:
void Log(const char* message);
void Log(const char* message);
You may have been confused with the one definition rule, which disallows defining things more than once.
I have removed the #pragma once statement, nor do I have header guards written, but my program still runs perfectly and without any problems.
If your header doesn't define anything, then it doesn't need a header guard. It's however simpler to just conventionally always keep the guard so that there is no need to keep track of whether there are definitions or not.
Bonus answer: All definitions are also declarations. It is usually easy to distinguish definitions of classes and functions from forward declarations:
return_type function_name(argument_list); // not a definition of function
return_type function_name(argument_list) { ... } // is a definition of function
class class_name; // not a definition of class
class class_name { // is a definition of class
void member_function(); // not a definition of function
void inline_member_function() { ... }; // is a definition of function
};
void class_name::member_function() { ... } // is a definition of function
Distinguishing variable definitions is a bit harder. Always check the rules when unsure.
this a function forward declaration and you just let the compiler know that a function X will be defined later. in some resources you will find out it's written/said that multiple declaration isn't allowed, but i think cuz of the clean code approach, not a compiler issue. and your case, you just include the declaration twice, the same if you declared the function in two different header files and included both of them in a source file.
Cherno's tutorials?
I think its made crystal clear in the videos that you can't have multiple definitions of a function. The custom header files that you've created are basically chunks of code copy-pasted hence if they include different definitions of the same function or say class it will result in ambiguity and throw an error as expected.
Edit: The point that he wanted to make -
If you write those two same function definitions together in a file then obviously it will throw up an error due to ambiguity arising as I mentioned above, which is detected by the compiler, since its only in a single file.
But when you place those two same definitions in a different file, say your custom created header "log.h" then when you import them into your cpp file twice (or say you import them in another cpp file and build the solution like in visual studio) it will throw up a linker error as the linker is involved (multiple files - wherein the job of the linker is to link them into a combined executable) and it cannot select multiple definitions present in different files. Hence for this case you will get the multiple definitions/signature error. (And including pragmas suppress warnings)
A Solution to resolve that is making the functions static, so that they are defined internally or only for the file they are being compiled against. This makes it possible to have multiple function definitions of the same function in different files with no linking error. Another option is to make it in-line. These cases provide you with multiple definitions with no errors, otherwise it will throw up errors.

Why do class member functions defined outside the class (but in header file) have to be inlined?

I have read existing answers on the two meanings of inline, but I am still confused.
Let's assume we have the following header file:
// myclass.h
#ifndef INCLUDED_MYCLASS
#define INCLUDED_MYCLASS
class MyClass
{
public:
void foo(); // declaration
};
inline void MyClass::foo()
{
// definition
}
#endif
Why does void foo() which is defined outside the class in the file, have to be explicitly defined with inline?
It's because you defined MyClass::foo in a header file. Or a bit more abstract, that definition will be present in multiple translation units (every .cpp file that includes the header).
Having more than one definition of a variable/function in a program is a violation of the one definition rule, which requires that there must be only one definition in a single program of every variable/function.
Note that header guards do not protect against this, as they only protect if you include the same header multiple times in the same file.
Marking the function definition as inline though means that the definition will always be the same across multiple translation units.1.
In practice, this means that the linker will just use the first definition of MyClass::foo and use that everywhere, while ignoring the rest,
1: If this is not the case your program is ill-formed with no diagnostics required whatsoever.
If you put MyClass::foo() in a header file and fail to declare it inline then the compiler will generate a function body for every compilation unit that #includes the header and these will clash at link time. The usual error thrown by the linker is something along the lines of Multiple definition of symbol MyClass::foo() or somesuch. Declaring the function inline avoids this, and the compiler and linker have to be in cahoots about it.
As you mention in your comment, the inline keyword also acts a hint to the compiler that you'd like the function to be actually inlined, because (presumably) you call it often and care more about speed than code size. The compiler is not required to honour this request though, so it might generate one or more function bodies (in different compilation units) which is why the linker has to know that they are actually all the same and that it only needs to keep one of them (any one will do). If it didn't know they were all the same then it wouldn't know what to do, which is why the 'classical' behaviour has always been to throw an error.
Given that the compilers these days often inline small functions anyway, most compilers also have some kind of noinline keyword but that is not part of the standard.
More about inline at cppreference.

Inline keyword vs header definition

What's the difference between using the inline keyword before a function and just declaring the whole function in the header?
so...
int whatever() { return 4; }
vs
.h:
inline int whatever();
.cpp:
inline int myClass::whatever()
{
return 4;
}
for that matter, what does this do:
inline int whatever() { return 4; }
There are several facets:
Language
When a function is marked with the inline keyword, then its definition should be available in the TU or the program is ill-formed.
Any function defined right in the class definition is implicitly marked inline.
A function marked inline (implicitly or explicitly) may be defined in several TUs (respecting the ODR), whereas it is not the case for regular functions.
Template functions (not fully specialized) get the same treatment as inline ones.
Compiler behavior
A function marked inline will be emitted as a weak symbol in each object file where it is necessary, this may increase their size (look up template bloat).
Whereas the compiler actually inlines the call (ie, copy/paste the code at the point of use instead of performing a regular function call) is entirely at the compiler's discretion. The presence of the keyword may, or not, influence the decision but it is, at best, a hint.
Linker behavior
Weak symbols are merged together to have a single occurrence in the final library. A good linker could check that the multiple definitions concur but this is not required.
without inline, you will likely end up with multiple exported symbols, if the function is declared at the namespace or global scope (results in linker errors).
however, for a class (as seen in your example), most compilers implicitly declare the method as inline (-fno-default-inline will disable that default on GCC).
if you declare a function as inline, the compiler may expect to see its definition in the translation. therefore, you should reserve it for the times the definition is visible.
at a higher level: a definition in the class declaration is frequently visible to more translations. this can result in better optimization, and it can result in increased compile times.
unless hand optimization and fast compiles are both important, it's unusual to use the keyword in a class declaration these days.
The purpose of inline is to allow a function to be defined in more than one translation unit, which is necessary for some compilers to be able to inline it wherever it's used. It should be used whenever you define a function in a header file, although you can omit it when defining a template, or a function inside a class definition.
Defining it in a header without inline is a very bad idea; if you include the header from more than one translation unit, then you break the One Definition Rule; your code probably won't link, and may exhibit undefined behaviour if it does.
Declaring it in a header with inline but defining it in a source file is also a very bad idea; the definition must be available in any translation unit that uses it, but by defining it in a source file it is only available in one translation unit. If another source file includes the header and tries to call the function, then your program is invalid.
This question explains a lot about inline functions What does __inline__ mean ? (even though it was about inline keyword.)
Basically, it has nothing to do with the header. Declaring the whole function in the header just changes which source file has that the source of the function is in. Inline keyword modifies where the resulting compiled function will be put - in it's own place, so that every call will go there, or in place of every call (better for performance). However compilers sometimes choose which functions or methods to make inline for themselves, and keywords are simply suggestions for the compiler. Even functions which were not specified inline can be chosen by the compiler to become inline, if that gives better performance.
If you are linking multiple objects into an executable, there should normally only be one object that contains the definition of the function. For int whatever() { return 4; } - any translation unit that is used to produce an object will contain a definition (i.e. executable code) for the whatever function. The linker won't know which one to direct callers to. If inline is provided, then the executable code may or may not be inlined at the call sites, but if it's not the linker is allowed to assume that all the definitions are the same, and pick one arbitrarily to direct callers to. If somehow the definitions were not the same, then it's considered YOUR fault and you get undefined behaviour. To use inline, the definition must be known when compiler the call, so your idea of putting an inline declaration in a header and the inline definition in a .cpp file will only work if all the callers happen to be later in that same .cpp file - in general it's broken, and you'd expect the (nominally) inline function's definition to appear in the header that declares it (or for there to be a single definition without prior declaration).

Why do I explicitly have to declare functions inline here?

Okay, up until now, I thought that functions defined in header files are treated like inline functions, just like template stuff, defined once, and all that.
I also use inclusion guards, yet I still got linker errors of multiple defined objects, and I know that is because of all those different units duplicating stuff the linker tries to pick out which item is the right one.
I also know that inline is merely a suggestion, and might not even get used by the compiler, etc.
Yet I have to explicitly define all those small functions in that little header only toolset I wrote.
Even if the functions were huge, I'd have to declare them inline, and the compiler would still possibly disregard the hint.
Yet I have to define them so anyway.
Example:
#ifndef texture_math_h__
#define texture_math_h__
float TexcoordToPixel(float coord, float dimension)
{
return coord * dimension;
}
float PixelToTexcoord(float pixel, float dimension)
{
return pixel / dimension;
}
float RecalcTexcoord(float coord,float oldDimension, float newDimension)
{
return PixelToTexcoord(TexcoordToPixel(coord,oldDimension),newDimension);
}
#endif // texture_math_h__
Errors are , blabla already defined in xxx.obj, for each unit that includes the file
When I declare all of those inline, it links correctly.
What's the reason for that? It's not a huge problem, and heck, optimizations probably inline stuff found in cpp, too, right?
I'm just curious about the why here, hope it's not too much of a duplicate and thank you for your time.
Inclusion guards only guard against the code being included twice in the same translation unit. So if you have multiple files that include the same header, the code is included multiple times. Functions defined in a header are not inline by default, so this will give you linker errors - you need to define those function with the inline keyword, unless they are member functions of a class.
Also, note that names that contain double-underscores are reserved for the purposes of the C++ implementation - you are not allowed to create such names in your own code.
Member functions are potencially inlined - you can't force inlining! - if (a) they are defined inside the class or if (b) you use the inline-clause in the definition. Note if you are using the inline-clause you shouldn't define the function in the header - the only exception would be templates as these are "special".
As you just updated the question:
Every user of this header will have a definition of the functions -> multiple defintions. You need to separate definition and declaration!
It's all about the one definition rule. This states that you can only have one definition for each non-inline function (along with various other types of entity) in a C++ program across all the translation units that you link in to make the program.
Marking a function inline enables an exception to the usual one definition rule. It states (paraphrased) that you can have one definition of an inline function per translation unit provided that all the definitions match and that a definition is provided in each translation in which the inline function is used.
Include guards will prevent you from accidentally providing more than one definition per translation unit by including the header file containing the definitions multiple times.
To satisfy the one definition rule for a non-inline function you would still have to ensure that there is only one translation unit containing the function definitions. The usualy way to do this is by only declaring the functions in the header file and having a single source file containing the definitions.

What's the difference between inline member function and normal member function?

Is there any difference between inline member function (function body inline) and other normal member function (function body in a separate .cpp file)?
for example,
class A
{
void member(){}
};
and
// Header file (.hpp)
class B
{
void member();
};
// Implementation file (.cpp)
void B::member(){}
There is absolutely no difference.
The only difference between the two is that the member inside the class is implicitly tagged as inline. But this has no real meaning.
See: inline and good practices
The documentation says that the inline tag is a hint to the compiler (by the developer) that a method should be inlined. All modern compilers ignore this hint and use there own internal heuristic to determine when a method should be inlined (As humans are notoriously bad and making this decision).
The other use of inline is that it tells the linker that it may expect to see multiple definitions of a method. When the function definition is in the header file each compilation unit that gets the header file will have a definition of the function (assuming it is not inlined). Normally this would cause the linker to generate errors. With the inline tag the compiler understands why there are multiple definitions and will remove all but one from the application.
Note on inlining the processes: A method does not need to be in the header file to inlined. Modern compilers have a processes a full application optimization where all functions can be considered for inlining even if they have been compiled in different compilation units. Since the inline flag is generally ignored it make no difference if you put the method in the header or the source file.
Ignore the word inline here and compiler hints because it is not relevant.
The big practical difference in A and B is when they are used in different libraries.
With the case of A you can #include the header and are not required to link against anything. So you can use this class from different applications / libraries without any special linkage.
With the case of B, you need B.cpp and this should be compiled only into one library / application. Any other library or application that needs to use this class will need to link against the one that contains the actual body of the code.
With some setups / implementations you will need to specifically mark the class as "exported" or "imported" between libraries (for example with Windows you can use dllimport / dllexport and with GNU you can use attribute(visibility="default") )
The first one is implicitly inline, i.e. suggesting the compiler to expand it at the call site.
Other than the inline thing, there's a difference in that you could put more definitions in between the definition of class B, and the definition of the function.
For example, B.cpp might include header files that B.hpp doesn't, which can make a significant difference to the build process for large projects.
But even without a separate translation unit, you can occasionally have a circular dependency that's resolved by separating the definitions. For example the function might take a parameter of a type that's forward-declared before B is defined, then defined by the time the function is defined. If that type uses the definition of B in its own definition, it can't just be be defined before B.