gtest problem with inline function - c++

hello i have which include inline function, when i try testing this class with google test, i have error like:
error LNK2019: unresolved external symbol "public: double __thiscall Math::returnPi(void)" (?returnPi#Math##QAENXZ) referenced in function "private: virtual void __thiscall Speed_Math_Test::TestBody(void)" (?TestBody#Speed_Math_Test##EAEXXZ)
for example my class(header file)
class Math
{
public:
Math(void);
inline double returnPi();
~Math(void);
};
my class(cpp file)
Math::Math(void)
{}
Math::~Math(void)
{}
double Math::returnPi()
{ return 3.14;}
test:
TEST(EQ, Math)
{
Math *m=new Math();
EXPECT_EQ(3.14,m->returnPi());
}
what i need to do? i read manual but dont see how i can resolved this error.

An inline function should be in your header file, not in your source file so it can actually be inlined by the callers (which don't have access to the source file).
Moreover, you don't need to specify inline in your class declaration if you give the definition of the function.
So your header should become:
class Math
{
public:
Math(void);
double returnPi() { return 3.14; } // no need to specify inline here
~Math(void);
};
And remove the definition for returnPi() from your source file.
Note that you could also have done:
class Math
{
public:
Math(void);
double returnPi();
~Math(void);
};
inline double Math::returnPi() { return 3.14; } // inline is mandatory here to avoid respecting the "One Definition Rule"
The second solution is good if you want to keep the class declaration separate from the function definition.
Also note that inline does not guarantees that the actual function calls will be inlined: the only thing it enforces is that you don't have to respect the "One Definition Rule": the inline function must have the same definition in all translation units.

Are you sure you are compiling the class' CPP file as part of the project? This should be fine.

Related

C++ inheritance - cannot define methods in cpp file

I have a following problem. I have these 3 files (I made a simplified example, but the errors are the same):
foo.hpp
#pragma once
#include <iostream>
class foo
{
protected:
virtual void bar() const noexcept = 0;
public:
foo() = default;
virtual void callbar() = 0;
};
class baz : public foo
{
protected:
void bar() const noexcept override;
public:
void callbar();
};
foo.cpp
#include "foo.hpp"
inline void baz::bar() const noexcept { std::cout << "baz::bar()" << '\n'; }
inline void baz::callbar() { bar(); }
main.cpp
#include "foo.hpp"
auto main() -> int
{
baz b;
b.callbar();
}
Compiler (actually the linker I guess) gives me the following error:
foo.cpp
main.cpp
Generating Code...
Microsoft (R) Incremental Linker Version 14.15.26729.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:foo.exe
foo.obj
main.obj
main.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl baz::bar(void)const " (?bar#baz##MEBAXXZ)
main.obj : error LNK2019: unresolved external symbol "public: virtual void __cdecl baz::callbar(void)" (?callbar#baz##UEAAXXZ) referenced in function main
foo.exe : fatal error LNK1120: 2 unresolved externals
Now I've gotten around this by doing either one of those two things:
Remove inline keyword
Leave inline as it is, but move the methods definitions to .hpp file
If I do one of those things, everything works. But my question is: why? In my real code I really wan the compiler to inline the method calls plus I want them to be defined in .cpp file, to make my .hpp file more clear. Is there a solution to that?
Your code has a bug in it. According to cppreference
The definition of an inline function or variable (since C++17) must be
present in the translation unit where it is accessed (not necessarily
before the point of access).
Obviously, when you put your definitions in .cpp file and call those functions from other translation units, this condition is not satisfied.
So your two alternative approaches both work because they either
Remove this condition altogether (when you remove inline specifier)
Make the definition visible
And last, but not the least - C++ inline specifier has nothing to do with function inlining. There are other, compiler-dependent ways to request the actual inlining, i.e. __forceinline in various compilers.

MFC projects cause "multiple definition" linker errors?

Is there something special about how an MFC project handles includes?
Here's the scenario. I like to define my class member functions in the h file, instead of splitting up a class between two files.
In Visual Studio I can create an empty Win32 project and do something like this:
main.cpp:
#include "doubleDef.h"
int main()
{
doubleDef t;
t.func();
return 0;
}
doubleDef.h:
#pragma once
class doubleDef
{
public:
int func();
};
int doubleDef::func()
{
return 4;
}
This builds just fine.
If I take doubleDef.h into an MFC dialog project, and add #include "doubleDef.h" to the h file of the main dialog, I get LNK2005, saying that func is already defined, making it seem as if the #pragma once is being ignored.
If I instead include doubleDef.h in the main dialog's cpp file, everything is fine. But in the empty Win32 I can include doubleDef.h "multiple times" by doing this:
Header.h
#pragma once
#include "doubleDef.h"
Header1.h
#pragma once
#include "doubleDef.h"
main.cpp:
#include "Header.h"
#include "Header1.h"
int main()
{
doubleDef t;
t.func();
return 0;
}
That is, it appears #pragma once works as expected (prevents multiple definitions of doubleDef::func()).
If I turn doubleDef into a template class, then the function definition must be in the h file. Likewise, I can make func inline, either by adding the keyword or implicitly by defining it next to the declaration in the class (as in int func() {return 4;}), and then, again the definition must be in the h file.
According to the documentation, the compiler treats inline as more or less optional, so it seems like if I just want to keep everything in the h file, I can just make everything inline.
What gives?
The #pragma once means the file will only be included once per source file. If you have many source files including it, you will still get a copy in each source file.
By declaring a function inline, you tell the compiler it's OK to have multiple copies - as long as those copies are identical.
The usual way of working is to have the declarations in the header file, and the definitions (implementation) in another source file.
P.S. MFC has nothing to do with your problems.
In your simple Win32 project you have one main file that keeps including the same item, basically a no-op. To have multiple of the same include in referenced in the same file does not create a new link.
However with your MFC project you put your header file into mainfrm.h. That file is included in several other files in that project not just the mainfrm.cpp. Essentially creating a new link for each of those other files the main header was included in.
1>MainFrm.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>FileView.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>ClassView.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>OutputWnd.obj : error LNK2005: "public: int __thiscall
doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in
MfcTest.obj 1>PropertiesWnd.obj : error LNK2005: "public: int
__thiscall doubleDef::func(void)" (?func#doubleDef##QAEHXZ) already defined in MfcTest.obj
Take a look at that output. You can see each of the other components that thinks it has that object.
To put it another way your original statement of why does it work for one way and not the other is because the complexity of the second example (MFC) actually includes that header all over the place. If you only want it used by the main form then include it in the cpp for it.
This was already answered before, here is more detailed explanation:
You cannot define a function more than once, unless it is inline
You cannot declare a function more than once in the same file.
You do need to declare functions and classes multiple times if they are referenced in multiple .cpp files.
#pragma once prevents multiple declarations in the same file. It will not prevent multiple declarations in different files. Multiple declarations is exactly what you want and it is why you are including the files in multiple .cpp files in the first place.
class N1 {
public:
//Declaration
//Multiple .cpp files need to know about this class and its members
int foo();
};
//Definition
//should be done once. This should go to .cpp file
int N1::foo() {
return 1;
}
In the above example, compile will work fine in multiple .cpp file. The compile routine does not notice multiple definitions. But the linker notices multiple definitions and complains. You have to move the definition to .cpp file or use inline functions.
class N2
{
public:
int foo();
};
inline int N2::foo()
{ //valid, even if it is repeated in different files
return 1;
}
class N3
{
public:
int foo() //always valid
{
return 1;
}
};

Compilation error while including cpp file in main: Inline versus non-inline functions

I have a conceptual doubt which i'll try to put across using an example:
main.cpp
#include "array_list.cpp"
int main()
{
array_list list1;
return 0;
}
Scenario1:
array_list.cpp->
class array_list
{
private:
int list[10];
public:
array_list () {};
~array_list () {};
void set_element (int,int);
};
void array_list::set_element (int i,int a) {
list[i] = a;
}
Error:
main.obj : error LNK2005: "public: void __thiscall array_list::set_element(int,int)" (?set_element#array_list##QAEXHH#Z) already defined in array_list.obj
1>C:\Users\vrastog\Documents\Visual Studio 2012\Projects\C++ learning\Debug\list using arrays.exe : fatal error LNK1169: one or more multiply defined symbols found
Scenario 2:
array_list.cpp->
class array_list
{
private:
int list[10];
public:
array_list () {};
~array_list () {};
void set_element (int i,int a) {
list[i] = a;
}
};
Error: No error!!
Question: I understand the reason for error. The same method has been defined twice, once in main.obj and second in array_list.obj and hence, it should be an error.
My question is why does the second scenario work? Here also, since we have includes array_list.cpp in the main file, 'set_element' should have been defined twice here as well. What am I missing here?
Please don't include .cpp files.
In the first example, the function is defined out of class, you need to add inline, otherwise it's a multiple definition.
In the second example, the function is defined in the class definition, so it's an implicit inline function (it's like the compiler added the inline for you), that's why it's not causing multiple definitions.
In-class definition makes a method inline, and therefore it does not cause a multiple definition error in the object file.
An inline method should be implemented in every translation unit it is used in, so the inline method compiles into both object files.
C++ Standard Draft (n3797) 3.2.4: An inline function shall be defined in every translation unit in which it is odr-used.
Also 3.2.6 requires that these function should be exactly the same.
g++ implements this using weak symbols: inline functions are special exported functions that do not cause multiple definition error when linking.
Use a tool like nm under Linux and see for yourself. It emits a weak symbol into the object file:
$ nm arraylist.o
00000000 W _ZN10array_list11set_elementEii
(... ctors, dtors ...)
00000000 T main
Also, if you do not use the function, or the compiler inlines all occurrences, it may get optimized out.

Inlining methods : drawbacks

I have a question concerning inlining methods.
I am using a library developed for collision models. One header file responsible for graphic interface contains declaration and implementation of the functions but the functions are not inlined. Therefore, it is impossible to include those functions in several translation units.
As an illustration here is a dummy code I designed for illustration :
LivingBeing.h
#ifndef LIVINGBEING_H
#define LIVINGBEING_H
class LivingBeing
{
public:
LivingBeing(double _size);
void breathe();
private:
double size;
};
//////////////
LivingBeing::LivingBeing(double _size)
{
size = _size;
}
void LivingBeing::breathe()
{
// do something
}
#endif
Forest.h
#ifndef FOREST_H
#define FOREST_H
#include "LivingBeing.h"
class Forest
{
public:
Forest(int _numberLivingBeings);
private:
int numberLivingBeings;
};
#endif
Forest.cpp
#include "Forest.h"
Forest::Forest(int _numberLivingBeings)
{
numberLivingBeings = _numberLivingBeings;
// Call LivingBeing constructor, methods etc...
}
Main.cpp
#include "Forest.h"
int main()
{
Forest forest = Forest(10);
return 0;
}
This code does not compile unless I add the inline keyword in front of the constructor LivingBeing and the method breathe. The error message is :
1>main_test.obj : error LNK2005: "public: __thiscall LivingBeing::LivingBeing(double)" (??0LivingBeing##QAE#N#Z) already defined in Forest.obj
1>main_test.obj : error LNK2005: "public: void __thiscall LivingBeing::breathe(void)" (?breathe#LivingBeing##QAEXXZ) already defined in Forest.obj
1>C:\Users\******\Documents\Visual Studio 2010\Projects\TutorialChronoEngine\Debug\Test_3.exe : fatal error LNK1169: one or more multiply defined symbols found
My question is : what is the drawbacks of inlining methods ? The real library I am using is pretty large, I would like to inline methods from a specific file (in my example it would be LivingBeing.h) so that it is possible to use those methods in several .cpp files. What am I risking by changing the source file as such ?
Thanks a lot
You are defining functions (LivingBeing::LivingBeing and LivingBeing::breathe) in a header, which means there will be a definition in each translation unit that includes that header. This breaks the One Definition Rule (ODR), hence the link error.
You have three options:
Move the function definitions into a source file so they are only defined once; or
Declare them inline to allow multiple identical definitions; or
Move the definitions inside the class definition, which implicitly makes them inline.
what is the drawbacks of inlining methods ?
Possibly increased compilation time and executable size; but you'd need to measure to see whether there's any noticable difference.
A less stable API - client code will need recompiling whenever any inline function changes.
The possibility of accidentally breaking the ODR, for example if a function contains macros which might have different expansions in different translation units.
Just because a method is defined in a "source" file (.c/.cpp) doesn't mean it won't be inlined... link-time operations may perform that optimization. Oppositely, just because a method is declared and implemented as inline in a header file doesn't mean it will be inlined. In general, I define methods in a header file if they are very simple, e.g. int getWidth() const { return width; }, or MyObj* getNext() { return internal_itor ? internal_itor->next : 0; }

Initializing static variables in static function result in unresolved

class PossibilisticShellClustering
{
public:
PossibilisticShellClustering(void);
~PossibilisticShellClustering(void);
static void SetParameters(double deltaDistance);
static double deltaDistance
};
and i wanto to initialize static variable deltaDistance in function SetParameters. So in *.cpp file I wrote
void PossibilisticShellClustering::SetParameters(double deltaDistance)
{
PossibilisticShellClustering::deltaDistance = deltaDistance;
}
however I get linker erros
unresolved external symbol "public:
static double
PossibilisticShellClustering::deltaDistance"
(?deltaDistance#PossibilisticShellClustering##2NA)
Could somebody tell me why ?
PossibilisticShellClustering.obj
You need to defined PossibilisticShellClustering::deltaDistance in a source file somewhere in your program, usually a .cc or .cpp file.
double PossibilisticShellClustering::deltaDistance;
What you have in the class body (or would have if it was terminated with a ;) is only a declaration. Static data members also need a definition.