Implementation Inside a Declaration C++ [duplicate] - c++

This question already has answers here:
multiple definition error including c++ header file with inline code from multiple sources
(6 answers)
Closed 5 years ago.
I want to include implementation of a function inside an .h file.
I know I would rather separate declaration and implementation to .h and .c file accordingly, this is not a part of my question.
When I implement the function inside the class, I receive no errors:
class Foo
{
public:
// Class constructor
Foo() { }
};
When I implement the function outside the class (still in the .h file):
class Foo
{
public:
// Class constructor
Foo();
};
Foo::Foo()
{
}
I receive the following error:
multiple definition of Foo:Foo()
Can someone explain me the logic behind this? Thanks.

This is because when you define the function in the class definition, the method is treated as an inline function. Which can be included in multiple source files, be compiled and linked together and still have the linker not complain about multiple definitions.
But when you define the constructor outside the class, #include it in multiple source files, compile them together and then link them. You get multiple definitions for the same function.
Remember that #includeing a file is essentially a copy paste of that file into the file that #includes it. So every time that file is included, you get a definition for the function in that source file. And then when you compile and link multiple such sources together you get multiple definitions for the same non-inline function.
For more see on inline, see http://en.cppreference.com/w/cpp/language/inline. The examples section has a good chunk of code that should help.
You can also explicitly mark the definition outside the class to be inline like #StoryTeller correctly noted.

Mark it inline
class Foo
{
public:
// Class constructor
inline Foo();
};
inline Foo::Foo()
{
}
Like Curious said, an in-class definition is implicitly inline. But if you define it outside the class, in a header, you must add the specifier explicitly.
The inline specifier is very important for correct linkage in cases like this. It allows the same function to exist in multiple translation units, so long as it's the exact same function body. A case that often occurs with functions defined in a header file.

Related

Extern for class method

I want to use extern keyword for class method in C++. I'm using Visual Studio 2019.
I want to force method inline, using __forceinline(without extern I will get unresolved external symbol). I don't want to put method implementation in this header file, I want put implementation in other .cpp file.
I noticed that method may be inlined automaticly without extern and __forceinline and when method's implementation in .cpp file. How can I force it?
Example code:
class Window {
public:
void Show();
};
That's ok!
class Window {
public:
__forceinline void Show();
};
Gets unresolved external symbol when I calls this function from other CPP.
With extern I gets:
screenshot
For simple functions extern __forceinline works fine:
screenshot
You cannot specify extern for a member function.
The standard clarifies this in [dcl.stc]/5:
The extern specifier can be applied only to the names of variables and functions. The extern specifier cannot be used in the declaration of class members or function parameters.
When you use extern, you say to the compiler that you declare a variable or a function, but without defining it. In the case of member functions, this is not needed: they can always be declared in a class body without being defined:
class A {
public:
void f(); // you can define it in which ever compilation unit (cpp) you want
};
...
// Else where...may be in another cpp
void A::f() {...}
The linker will resolve the symbols when needed.
The inline is not so useful
The standard in [dcl.inline]/2 says that inline is not guaranteed:
The inline specifier indicates to the implementation that inline
substitution of the function body at the point of call is to be
preferred to the usual function call mechanism. An implementation is
not required to perform this inline substitution at the point of call;
Furthermore, [dcl.inline]/6 explains that inline and defined eleswhere is not something meant to work well:
An inline function or variable shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case.
(odr says that all the definitions must be exactly the same definition each time)
(in every translation unit means in every cpp or the headers therein included)
On the other side, the global optimizer of some modern compilers is able to achieve similar performance effects than inlined functions, and this accross compilation units (cpp).
Implementation specific forceinline
MSVC 2019 uses inline carefully, making a cost/benefit analysis to decide whether or not to inline.
forceinline allows you to overrule the compiler's judgement. But it comes with all the requirements of the normal inline: so you need to have a definition of the function in the same compilation unit to get it work.
Two things:
You cannot declare a member function as extern. These already have external linkage.
For the compiler to inline a function or method, it has to be defined (as opposed to declared) in the header file. This is so that the compiler can see it when compiling code that calls the function.
So, just put the function body in the header file and drop the extern.
I don't want to put method implementation in this header file, I want put implementation in other .cpp file.
Sounds to me like you just want to have all declarations in one file like this:
This is your window.h- file:
class Window
{
public:
void Show();
};
To have the implementation in another file, you have to use the scope operator.
This is the other window.cpp- file, in which you have the actual implementation of the function:
#include "window.h"
Window::Show()
{
// Your implementation goes here
}
I hope I understood your question right and this helps.

Undefined reference when inline specifier used with class member [duplicate]

This question already has answers here:
C++ inlining class methods causes undefined reference
(3 answers)
Closed 1 year ago.
I have some member functions in a class. When I use the inline specifier, the compiler complains of undefined reference.
I have tried:
Using 'inline' to precede the function definition in the class header file only.
Using 'inline' to precede the function declaration in the class .cpp (where the member functions are specified) file only.
Doing both of the above at the same time.
Obviously, one of these ways is the correct thing to do, and the others are not correct. However trying each option did not get me a program which compiled.
Here is what I am trying to do:
.hpp file:
class A{
void func();
}
.cpp file:
... include ...
inline void A::func()
{
...
}
Or maybe 'inline' goes elsewhere. I have tried all possible combinations I could think of, as I explained above. (Now watch someone tell me I need it AFTER the function name and arguments, like the keyword 'const'.)
Anyone any ideas on what I am doing wrong? I tried googling what the correct answer might be, but no luck. Are 'inline' functions inside a class even a thing?
Inline functions have to be defined in header files. The definition (the body) of the function has to be visible in all translation units that attempt to use that function. You can define it directly inside the class. Or you can define it as in your code, i.e. outside of the class. But it has to be in header file, not in .cpp file.
Attempting to define an inline function in .cpp file will make it usable in that .cpp file only. Trying to use it in other .cpp files will lead to linker errors (i.e. "undefined reference" errors).
Putting inline anything inside the CPP file can only possibly inline the function inside that file. If you want to encourage the compiler to inline the function, you need to forget about the CPP file. Instead, do this in the hpp file:
class A{
inline void func();
};
void A::func() {...}
NB a few points:
Putting inline doesn't mean your function will be inlined. It's a hint to the compiler.
You need optimization (-O3 in gcc) to even have a chance at it being inlined
If you define the function inside the class, it implicitly has the inline keyword on:
class A{
inline void func() {
...
}
};
is the same as the above where it was declared inline in the class and the definition was outside.
There are ways to force GCC to inline your code using function attributes, but I will not describe them because it is rarely a good idea to use them. GCC should do the "best" thing regarding inlining for each function. Forcing it to do something else will almost always result in worse performance.

What happens if I implement a class in the header file? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Inline functions in C++
What does the compiler do if I completely implement a class in its header file? A typical example follows:
class MyException
{
public:
explicit MyException(const char* file, int line) file(file), line(line) {};
const char* getFile() const { return file };
int getLine() const { return line };
private:
const char* const file;
const int line;
};
My intention is to use the class like this: throw MyException(__FILE__, __LINE__).
I include this header file into each .cpp file. I suppose the compiler will compile the class as many times as it is defined and include the (identical) machine code into every object file it produces. Now, what will the linker do? I tried a simpler example (without all those pesky const's) and it compiled fine.
What would happen, if instead of a simple class, I implemented a three-screenful-long C function in a header file? And the final question, should I split my example into .h and .cpp files?
All methods will be inline methods. You may loose some minimal time on the overall compilation, but it's ok. As far as I know the only problem that can occur is if you have a static non-cost member variable. Then you have to assign a storage place for it (place a definition and and initial value if you want) presumably in a .cpp or else you will get linker errors about multiple definition.
I've seen header-only projects which had only the main() function in a CPP, but that was heavily templated.
Update for C++17: You can declare static non-const members as inline in your header file since C++17. This makes header-only libraries easily possible without gymnastics like static variables inside inline functions.
A class definition itself doesn't produce any code. It just shows users of the class how it is layed out, so they can generate appropriate code to manipulate it.
It's the member functions of the class that generate code. When you define a member function inside the class definition it gives the function an implicit inline declaration.
A function call can be compiled and linked in one of two ways:
(1) A single copy of the function code with a RETURN assembly instruction at the end can be placed in the image, and a CALL assembly instruction can be placed (along with param passing and return value transfer) at the call site to transfer control to this code.
or
(2) An entire copy of the function implementation can replace the entire function call at the call site.
A function declared inline is a recommendation to the compiler to do it the second way. Further an inline declaration allows the function to be defined in several translation units (so it can be placed in a shared header file). In order for the compiler have the option of implementing the second method, it needs a copy of the function implementation at compile-time. This isn't available if the function implementation is in a foreign translation unit.
It should also be noted that modern compilers do complicated things with functions declared inline. See:
http://gcc.gnu.org/onlinedocs/gcc/Inline.html
When you implement member functions inside a header file, all those functions become implicitly inline.
What does this mean and what implications does it have?
As per,
C++03 Standard ยง7.1.3/4:
It hints the compiler that substitution of function body at the point of call is preferable over the usual function call mechanism.
Even if the inline substitution is omitted, the other rules(especially w.r.t One Definition Rule) for inline are followed.
So Yes, every translation unit will have the definition of the inline function.This may result in increase in the size of your binaries.
Usually any good mainstream compiler will substitute function body at the point of call if needed, so marking functions inline merely for #1 is not really a good idea but if you want to make your intent clear to users of your class then you can do so by defining the functions within the header or explicitly marking your functions as inline.
Should I split my example into .h and .cpp files?
Yes, that is the usual compilation model that most of the projects use, wherein you separate the interface(.h) from the implementation(.cpp).The interfaces are shared with the users of your code as header files while the implementation is provided in the form of binaries.To some extent this provides a safeguard to your intellectual property.
This is known as the Separation Model.
C++ projects using templates will usually use the Inclusion Model rather than the Separation Model of usual C++ projects.

How do you declare a class inline?

My homework assignment is telling me to declare a class inline, but I've only heard of declaring functions inline. What does an inline class declaration do, and how do you achieve it?
I think they are just saying that your classes should go in the header, and for convenience all the class methods should be declared inline in the class itself, instead of putting the class methods out-of-line or into a separate CPP.
It's slightly ambiguous but that's how I'd interpret it.
Comparing functions and classes:
A function can have a declaration and a definition:
ReturnType FunctionName(Parameter1, Parameter2); // a function declaration
ReturnType FunctionName(Parameter1, Parameter2) // a function definition
{
// do something
return ReturnType;
}
The function declaration gives all the information anyone needs who wants to call the function.
The function definition allows the compiler to generate machine code so that when someone calls the function there will be instructions somewhere in the executable that will be called.
This generated code exists only once in the executable. Usually you would put the function definition in a .cpp file (or .c if you're using C, this applies there too), which is compiled and linked into the executable. If that .cpp file isn't linked you will get a linker error saying FunctionName not found or something like that.
If you put the function definition in a header file it is more than likely that the header will be used in multiple places in your system, and included into other .cpp files. This will produce the opposite problem at link time FunctionName already defined in this, that, or the other object file.
So, functions usually aren't defined in header files because the header is usually included in multiple .cpp files so would end up producing duplicated object code.
With classes however it's slightly different. You have two different ways of defining a function for a class. One way is similar to how functions are defined above:
//myleanklass.h
class MyLeanKlass
{
public:
void perform();
};
//myleanklass.cpp
void MyLeanKlass::perform()
{
// Sing, dance, and play the piano
}
Just as with a free function we could have put the definition in the header file, as long as it wasn't included in more than one .cpp file. Otherwise we'd get a similar linker error again void MyLeanKlass::perform already defined ... This scenario is not the norm though. You usually declare classes so that they can be reused through a system. So the header will be included in multiple places and lead to linker errors.
Just to be clear, we could have put the definition in the header file, but not inline. You wouldn't be able to include this header multiple times in your system:
class MyLeanKlass
{
public:
void perform();
};
void MyLeanKlass::perform()
{
// Sing, dance, and play the piano
}
Finally then, we get to the answer to the question. You can define class functions in the header file as long as they are within the class declaration. This is called inline definition. Even if the header is included in multiple .cpp files it won't lead to multiple definitions in compilation units and won't cause linker errors.
//myleanklass.h
class MyLeanKlass
{
public:
void perform()
{
// Sing, dance, and play the piano
}
};
However, there are problems with this approach:
Inlining class functions is likely to make compilation take longer as the compiler will still compile every repeated definition of class functions and only throw away the duplicates at link time.
Making changes to class functions causes a recompilation of any .cpp file which includes it, again leading to longer re-compilation times.
Sometimes it just won't be possible. If a class uses another class and that uses the other class, you're going to have a cyclic dependency and it won't be possible to define everything inline. You can solve that by just putting the problem functions into a separate .cpp file.

strange redefined symbols

I included this header into one of my own: http://codepad.org/lgJ6KM6b
When I compiled I started getting errors like this:
CMakeFiles/bin.dir/SoundProjection.cc.o: In function `Gnuplot::reset_plot()':
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++-v4/new:105: multiple definition of `Gnuplot::reset_plot()'
CMakeFiles/bin.dir/main.cc.o:project/gnuplot-cpp/gnuplot_i.hpp:962: first defined here
CMakeFiles/bin.dir/SoundProjection.cc.o: In function `Gnuplot::set_smooth(std::basic_string, std::allocator > const&)':
project/gnuplot-cpp/gnuplot_i.hpp:1041: multiple definition of `Gnuplot::set_smooth(std::basic_string, std::allocator > const&)'
CMakeFiles/bin.dir/main.cc.o:project/gnuplot-cpp/gnuplot_i.hpp:1041: first defined here
CMakeFiles/bin.dir/SoundProjection.cc.o:/usr/include/eigen2/Eigen/src/Core/arch/SSE/PacketMath.h:41: multiple definition of `Gnuplot::m_sGNUPlotFileName'
I know it's hard to see in this mess, but look at where the redefinitions are taking place. They take place in files like /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/include/g++-v4/new:105. How is the new operator getting information about a gnuplot header? I can't even edit that file. How could that ever even be possible? I'm not even sure how to start debugging this. I hope I've provided enough information. I wasn't able to reproduce this in a small project. I mostly just looking for tips on how to find out why this is happening, and how to track it down.
Thanks.
You're obviously violating the "one definition rule". You have lots of definitions in your header file. Some of them are classes or class templates (which is fine), some of them are inline functions or function templates (which is also fine) and some of them are "normal" functions and static members of non-templates (which is not fine).
class foo; // declaration of foo
class foo { // definition of foo
static int x; // declaration of foo::x
};
int foo::x; // definition of foo::x
void bar(); // declaration
void bar() {} // definition
The one definition rule says that your program shall contain at most one definition of an entity. The exceptions are classes, inline functions, function templates, static members of class templates (I probably forgot something). For those entities multiple definitions may exist as long as no two definitions of the same entity are in the same translation unit. So, including this header file into more than one translation unit leads to multiple definitions.
Looks like you include conflicting headers. Try to check your include paths. They usually are defined in -I directive (at least in gcc) or in an environment variable.
Reading compiler errors usually helps. You should learn to understand what the compiler is telling you. The fact that it is complaining about a symbol being redefine is saying that you are breaking the One Definition Rule. Then it even tells you what the symbols are:
class GnuPlot {
//...
GnuPlot& reset_plot(); // <-- declaration
//...
};
//...
Gnuplot& Gnuplot::reset_plot() { // <-- Definition
nplots = 0;
return *this;
}
You can declare a symbol as many times as you wish within a program, but you can only define it once (unless it is inlined). In this case the reset_plot is compiled and defined in all translation units that include the header, violating the One Definition Rule.
The simplest way out of it is declaring it inline, so that it can appear in more than one compilation unit and let the linker remove the redundant copies (if any) later on.
A little more problematic are the static members that must be declared within the class and defined (only once) in a translation unit. For that you can either create a .cpp file to define those variables (and any function/method that you don't need inlined in the header).