C++ inheritance - cannot define methods in cpp file - c++

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.

Related

How to fix C++ linker error with no explaination

I have a C++ project that won't compile, and the following 2 errors are produced:
Error LNK1120 1 unresolved externals
Error LNK2019 unresolved external symbol "public: virtual __cdecl
StartWindow::~StartWindow(void)" (??1StartWindow##UEAA#XZ) referenced
in function "public: void __cdecl StartWindow::`vbase
destructor'(void)" (??_DStartWindow##QEAAXXZ)
StartWindow is a class I have defined, but currently it is never instantiated or included anywhere in the project. Deleting the class allows the project to compile, but if this class is within the project it won't.
I will include the code for the class in case I am missing something:
.CPP File
#include "StartWindow.h"
StartWindow::StartWindow()
{
setImmediateDrawMode(false);
}
void StartWindow::onDraw()
{
clearScreen(WHITE);
EasyGraphics::onDraw();
}
Header File:
#pragma once
#include "EasyGraphics.h"
class StartWindow : public EasyGraphics
{
public:
StartWindow();
~StartWindow();
private:
virtual void onDraw();
};
Thanks.
You're missing the implementation for the destructor for StartWindow. In your implementation file (.cpp file), append:
StartWindow::~StartWindow(){
//if your destructor is non-trivial, include definition here
}

Visual C++ 2015 linker error when forward declaring a struct as class

I have the following code (more than one file involved)...
//--- SomeInterface.h
struct SomeInterface
{
virtual void foo() = 0;
virtual ~SomeInterface(){}
};
//--- SomeInterfaceUser.h
#include <memory> //shared_ptr
class SomeInterface;
//NOTE: struct SomeInterface... causes linker error to go away...
class SomeInterfaceUser
{
public:
explicit SomeInterfaceUser(std::shared_ptr<SomeInterface> s);
};
//SomeInterfaceUser.cpp
#include "SomeInterfaceUser.h"
#include "SomeInterface.h"
SomeInterfaceUser::SomeInterfaceUser(std::shared_ptr<SomeInterface> s)
{
}
//SomerInterfaceUserInstantiator.cpp
#include "SomeInterfaceUser.h"
#include "SomeInterfaceImpl.h"
struct SomeInterfaceImpl : SomeInterface
{
virtual void foo(){}
};
void test()
{
SomeInterfaceUser x{std::make_shared<SomeInterfaceImpl>()};
}
Using the Visual C++ compiler, I get a linker error (LNK2019). Using GCC 4.8.4 this is not the case. Changing the forward declaration class SomeInterface to struct SomeInterface makes the linker error go away. I always thought that one should be able to use class/struct interchangeably? The interface of SomeInterfaceUser should not depend on whether SomeInterface is defined as class or struct, not so?
Is this a Visual C++ bug. I cannot find anything relating to it. I suspect the fact that the struct is used as template parameter has something to do with it.
Your help appreciated.
I've just been facing the same problem with both VC++ 2010 and VC++ 2017, and after some tests I've found that the problem resides in the symbol name the compiler gives to structs and classes internally.
Here a minimum example consisting in three files:
main.cpp
#include "bar.h"
struct Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
bar.h
class Foo;
void bar(Foo* f);
bar.cpp
#include "bar.h"
void bar(Foo* foo) {}
When the project is compiled the following errors and warnings appear:
warning C4099: 'Foo': type name first seen using 'class' now seen using 'struct'
see declaration of 'Foo'
error LNK2019: unresolved external symbol "void __cdecl bar(struct Foo *)" (?bar##YAXPAUFoo###Z) referenced in function _main
fatal error LNK1120: 1 unresolved externals
Now, I swapped the struct and class declarations, so main.cpp and bar.h are now:
main.cpp
#include "bar.h"
class Foo {};
int main() {
Foo foo;
bar(&foo);
return 0;
}
bar.h
struct Foo;
void bar(Foo* f);
As expected, the error still pops up:
error LNK2019: unresolved external symbol "void __cdecl bar(class Foo *)" (?bar##YAXPAVFoo###Z) referenced in function _main
BUT, and this is the interesting part, see that the symbols for the expected function (the one used in main()) in each case differ:
?bar##YAXPAUFoo###Z (when the parameter is a struct)
?bar##YAXPAVFoo###Z (when the parameter is a class)
Conclusion
The compiler gives slightly different names if the type is a struct or a class.
The linker then cannot find the proper definition because it is looking for a different one: bar.cpp defines one with the forward declaration, but for the moment it is called in main.cpp the actual declaration has taken placed, so a different function name is given in the symbols table.
Update (2023-02-03)
I've just seen that clang is able to report this issue:
error: 'Foo' defined as a struct here but previously declared as a class; this is valid, but may result in linker errors under the Microsoft C++ ABI [-Werror,-Wmismatched-tags]

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.

C++ Unresolved external symbol (LNK2019)

I've spent the last 2 days searching for and implementing the answers from similar questions into my code with little success. I have an API that is an external .dll (windows) and I have the header file included into my .cpp file to reference the API.
However I have this issue that no matter what I do, I always get an unresolved external symbol that references this line in my .h file. Yes, I have used Google and modified the answers I found into my code, with no success.
Foo.h
Class Foo {
public:
static Foo* Interface_Get(char* dllfilename);
Foo.cpp
// I declare this just underneath the #include "Foo.h" header
Foo *foo = 0;
Inside my main function I declare it as this (along with some other functions that are fine).
//This has already been created and both Header and .dll are in the same directory.
Foo::Interface_Get("bar.dll");
And I get this error
error LNK2019: unresolved external symbol
"public: static class Foo * __cdecl Foo::Interface_Get(char *)"
I've tried everything I know (This is my first .dll creation experience) I have a feeling I am missing something painfully obvious, but for the life of me I cannot see it.
Entire Foo.cpp
#include "Foo.h"
Foo* Foo::Interface_Get(char* dllfilename); //May not be redeclared outside class error
Foo* foo = 0;
bool Frame()
{
if (foo->Key_Down(DIK_ESCAPE))
return false;
return true;
}
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
foo->Interface_Get("bar.dll");
foo->System_SetState(grSTATE_FRAME, Frame);
foo->System_SetState(grSTATE_WINDOWED, true);
foo->System_SetState(grSTATE_KEYBOARD, true);
foo->System_Initiate();
foo->System_Start();
foo->System_Shutdown();
foo->Inferface_Release();
return 0;
}
This question explains common problems, and in your case it's (probably) a combination of:
(possibly) forgetting to implement the function
forgetting __declspec(dllexport)
forgetting to link against the library
You need to provide function definition for Interface_Get(char* dllfilename); if you haven't done that.
This only redeclares function again, you need to provide function like below format with {}
Foo* Foo::Interface_Get(char* dllfilename); //May not be redeclared outside class error
Foo.cpp
Foo* Foo::Interface_Get(char* dllfilename)
{
//....
return new Foo();
}

gtest problem with inline function

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.