Why am I getting this warning in Qt Creator: ` inline function ‘bool Lion::growl ()’ used but never defined?
I double-checked my code, and have a declaration
inline bool growl () in Lion (lion.h)
and the corresponding implementation in lion.cpp:
inline bool Lion::growl ()
What’s going on?
EDIT: My assumption has been that it is legal to define the actual inline method in the .cpp file (the inline keyword alerts the compiler to look for the method body elsewhere), or am I mistaken?
I don't want to clutter my header files with implementation details.
Well, I don't know the exact problem, but for starters:
Inline methods are supposed to be implemented in the header file. The compiler needs to know the code to actually inline it.
Also using the "inline" keyword in the class declaration doesn't have any effect. But it cannot hurt either.
See also: c++ faq lite
Inline methods are supposed to be implemented in the header file. The
compiler needs to know the code to actually inline it.
Except if the inline function is used in the same project, possibly in another file that #include its header.
I miss there is such a restriction for libraries because restricting headers to function prototypes make things more readable.
What about #include-ing the .cpp ?
In addition to what Johan said, you cannot have a separate definition and declaration for the function even if both are in the same header file. This holds true especially for member functions of classes. The function code should be of the form:
class someClass
{
void someFunc()
{ ... }
}
// This will make the function inline even w/o the explicit 'inline'
And NOT of the form
class someClass
{
public:
void someFunc();
}
void someClass::someFunc()
{ ... }
Related
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.
For C programs, I know I need .h, and .cpp to allow multiple .h to be read and compiled together but linked later.
However, for C++, I don't want to break up the class member function declaration and definition to two parts. Although it is the typical C++ way, I am trying to merge member function declaration and definition in one header file. I saw some people doing that. I would like to know if there is any problem to do this.
I know all members defined in .h class definition are then inline functions, but can they be non-inline in any way? Will compiler be controllable so that they don't have to be inline, for example, when the function is huge?
The VS2015 intellisense shows error when the 2s is in a member function defined in header file, but doesn't show that in cpp file. But it compiles. Is it showing that I am doing it wrong, or it's a bug for VS2015? I deleted the sdf, restarted the project, as long as copy the function into the .h file, it shows a read line under std::this_thread::sleep_for(2s);
see
class testtest {
void tryagain() {
using namespace std::chrono_literals;
auto twosec = 2s;
std::this_thread::sleep_for(2s);// problem is here
}
};
Is compiling faster if we separate the .h and .cpp?
My final compiler would be g++4.9.2, and I am using VS2015 to test build. The final code will run on an ARM with 1GB RAM on Linux.
I don't intend to argue about wich style is better, but hope to focus on whether it works, and what are the trade offs.
It is perfectly fine to place all implementation code in the .h file if you want, it usually depends on the situation. It's usually good practice to split up the interface and implementation even if all the code is in the .h file by doing something like this
class MyClass {
public:
void doSomethingUseful();
};
....
void MyClass::doSomethingUseful() {
// code goes here....
}
Not all functions will automatically be inlined, the compiler usually decides what to inline or not. Larger functions will likely not be inlined even if they're in the header. You can use the inline keyword to give a hint to the compiler that you'd like the function to be inlined but this is no guarantee (also as a small aside, functions marked as inline in a .cpp file will be inlined, but only when called from other functions within that same .cpp file)
Compile times will be slower with more code in the .h file so it's best to try and reduce the amount of code in them as much as possible. I guess in your case though it shouldn't be that noticeable.
I hope that is of some help! :)
You can put defines around functions to prevent them being implemented more than once
header file:-
class MyClass {
public:
void doSomethingUseful();
};
// inline functions
....
// non inline function
#ifdef MYCLASSCPP
void MyClass::doSomethingUseful() {
// code goes here....
}
#endif
Then define MYCLASSCPP in just one CPP file. (or complier parameter).
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.
I always try to keep implementation outside of headers, so for templates and inlined functions, I usually do something like this
// File.h
inline bool foo()
#include "File.hpp"
// File.hpp
inline bool foo()
{
return 1;
}
My question is, what does the C++ specification have to say about repeating the inline keyword for the actual implementation of the function? (as shown in this example)
I don't really want to do that as it gets messy with lots and lots of functions, and while my compiler doesn't complain, I wonder if the compiler still accepts the inline hint.
Anyone know?
I tend to put inline as far from the interface as possible since it is an implementation detail and not part of the interface. Hence: omit the first inline in the declaration. And only attach it to the function definition. For the inclusion of an hpp compiler scopes are irrelevant in respect to inline since the files are treated as concatenated.
See also http://www.parashift.com/c++-faq/where-to-put-inline-keyword.html for a more detailed explanation.
It's OK, but putting inline in the source file is even less of a hint, because the sources aren't generally visible to other translation units. If you implement the function outside the header, the compiler will probably not be able to inline it anyways.
The only practical use of inline, in my opinion, is to prevent multiple definition of functions defined in the header.
Lets say you have simple template function (not class member for the sake of simplicity) with type specific specialization in the same .h file...
template <class TYPE>
void some_function(TYPE& val)
{
// some generic implementation
}
template <>
inline void some_function<int>(int& val)
{
// some int specific implementation
}
Unless you explicitly direct you compiler to inline the specialization (inline keyword) you will get linking error if .h file is included more than once (at least I do in Visual C++ 2008).
We all know that inline is just a suggestion to the compiler, which it can ignore. In this particular case is compiler allowed to ignore this suggestion and let linker to fail?
If you don't use inline, then the same function gets compiled with extern linkage into multiple .obj files, which causes the linker to throw a duplicate symbol error.
This is independent of whether the compiler actually compiles your function inline, since it could treat it the same as a static function and make each implementation private to each compilation unit. However, you can't use static for this purpose since it means something else on member functions, so inline is your only choice.
You are misunderstanding the meaning of the often-mentioned "ignore inline" possibility.
No compiler is ever allowed to ignore the inline specifier used in function declaration and the consequences this specifier has with respect to One Definition Rule (ODR).
When someone says that compiler are allowed to "ignore inline", it only means that compilers are not required to actually inline the calls to the function in question. To "ignore inline" means to generate an ordinary (non-inlined) function call to an inline function.
In any case, even if the compiler decided to always generate ordinary calls to an inline function (i.e. to always "ignore inline"), it is still required to treat the function as inline for the purposes of ODR. How the compiler is going to do it is the problem of the compiler. You are not supposed to worry about it.
In your original example you should not not get any linker errors.
This is defined by the standard and the compiler is totally compliant in this regard, from the looks of it. The linkage is all you are after. Implicit template instantiations have 'special' linkage, as inline functions do. There is also static (keyword), which has been deprecated in favor of anonymous namespaces:
namespace {
…declarations…
}
So yes, this specialization (in your example) has the same linkage as:
void some_other_function(int& val) {
// some int specific implementation
}
In fact, the compiler may mumble about inlining the specialization, in your example, saying they do not match. So it really is a best practice to label them both inline (or otherwise).
I believe you can explicitly declare the method as extern and then put the specialization into a .cpp. I've tried something similar in a past life with GCC, but I don't recall the exact details of how it worked. MSDN Magazine has an article on this that might help.
What you're actually seeing is the One Definition Rule (ODR) has a special case for inline functions, in that each TU may have a definition. If the function, such as your explicit int specialization, is not inline, then you will get multiple definition errors at link time. Such inline functions still have external linkage. Function templates are templates and so follow different rules. Instantiations/specializations of a function template are functions.
Using inline, as for any function, is just a hint, but you might want to apply it if the function is short (as for any function) or if you just want to keep it in the header. Here's an example without inline:
Header file:
template<class TYPE>
void some_function(TYPE& val) {
// some generic implementation
}
template<>
void some_function<int>(int& val);
Implementation (.cpp) file:
template<>
void some_function<int>(int& val) {
// some int specific implementation
}