So I am currently working on a basic game engine with a collision system. For that system I have a CollidableGroup template class which objects register themselves too. However, I am not super experienced with templates and am running into an unresolved external error.
The class is a Singleton and the problem is comming from my GetInstance() method which is being called in the register/deregister.
Here is the code:
#ifndef CollidableGroup_
#define CollidableGroup_
#include "ContainerAlias.h"
//#include "Collidable.h"
template<class CollidableType>
class CollidableGroup {
public:
static const KL::CollidableList& GetCollideableCollection() {
GetInstance().PrivateGetColliableCollection();
};
static void Register(CollidableType& collidable_) {
GetInstance().PrivateRegister(collidable_);
};
static void Deregister(CollidableType& collidable_) {
//GetInstance().PrivateDeregister(collidable_)
};
private:
CollidableGroup();
CollidableGroup<CollidableType>(const CollidableGroup<CollidableType>&) = delete;
CollidableGroup<CollidableType>& operator=(const CollidableGroup<CollidableType>&) = delete;
~CollidableGroup() {
instance = nullptr;
};
static CollidableGroup<CollidableType>* instance;
static CollidableGroup<CollidableType>& GetInstance() {
if(!instance)
{
instance = new CollidableGroup<CollidableType>;
}
return *instance;
}
void Delete() {};
KL::CollidableList mCollidableCollection;
void PrivateDeregister(CollidableType&) {};
void PrivateRegister(CollidableType& collideable_) {
mCollidableCollection.insert(mCollidableCollection.end(), &collideable_);
};
const KL::CollidableList& PrivateGetColliableCollection() {
return mCollideablCollection;
};
};
template <typename CollidableType>
CollidableGroup<CollidableType>* CollidableGroup<CollidableType>::instance = nullptr;
//template<class CollidableType>
//inline void CollidableGroup<CollidableType>::Register(CollidableType & /*collidable_*/) {
// GetInstance();// .PrivateRegister(collidable_);
//};
#endif //!CollidableGroup_
ERROR:
1>------ Build started: Project: KatanaEngine, Configuration: Debug Win32 ------
1>Tank.cpp
1>Tank.obj : error LNK2019: unresolved external symbol "private: __thiscall CollidableGroup<class Tank>::CollidableGroup<class Tank>(void)" (??0?$CollidableGroup#VTank####AAE#XZ) referenced in function "private: static class CollidableGroup<class Tank> & __cdecl CollidableGroup<class Tank>::GetInstance(void)" (?GetInstance#?$CollidableGroup#VTank####CAAAV1#XZ)
1>C:\Users\David_Desktop\Perforce\dklimavi_DESKTOP\berthiaume2018winter_gam374\student\dklimavi\Sprint_6\katanaenginerep\KatanaEngine\Debug\KatanaEngine_Debug.exe : fatal error LNK1120: 1 unresolved externals
1>Done building project "KatanaEngine.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
mostly what #drescherjm said, you declared a constructor, but the implementation isn't in your template definition, in the .h
CollidableGroup();
You should at least do something like this:
CollidableGroup() = default;
or
CollidableGroup() {};
if you implemented it in the .cpp, it won't work. You need to write the implementation in the h file when you work with template.
Related
I have solution with 2 projects inside. In first project which is builded as library I have templated class
a.h
#pragma once
#include <memory>
template<class MessageType, class HandlerType>
class A
{
std::unique_ptr<MessageType> msg;
std::unique_ptr<HandlerType> handler;
public:
A() : msg(std::make_unique<MessageType>()), handler(std::make_unique<HandlerType>()) {}
virtual ~A() {}
};
Then derived class
b.h
#include "a.h"
#include <string>
struct MyMessage
{};
struct MyHandler
{};
class B : A<MyMessage, MyHandler>
{
std::string name;
public:
B(const std::string& str);
virtual ~B();
};
and implementing it
b.cpp
#include "b.h"
B::B(const std::string& str)
{
}
B::~B()
{}
This code builded as static library (.lib). But when I try in main project to use instance of B class:
process.cpp
#include <iostream>
#include "b.h"
int main()
{
std::cout << "Hello World!\n";
B opa("yes");
}
compiler can't link it
Rebuild started...
1>------ Rebuild All started: Project: ConsoleApplication3, Configuration: Debug Win32 ------
1>b.cpp
1>ConsoleApplication3.cpp
1>Generating Code...
1>ConsoleApplication3.vcxproj -> C:\Users\user\source\repos\tmpClass\Debug\ConsoleApplication3.lib
2>------ Rebuild All started: Project: tmpClass, Configuration: Debug Win32 ------
2>process.cpp
2>process.obj : error LNK2019: unresolved external symbol "public: __thiscall B::B(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0B##QAE#ABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) referenced in function _main
2>process.obj : error LNK2019: unresolved external symbol "public: virtual __thiscall B::~B(void)" (??1B##UAE#XZ) referenced in function _main
2>C:\Users\user\source\repos\tmpClass\Debug\tmpClass.exe : fatal error LNK1120: 2 unresolved externals
2>Done building project "tmpClass.vcxproj" -- FAILED.
========== Rebuild All: 1 succeeded, 1 failed, 0 skipped ==========
LNK2019 means that the corresponding lib file is not added. You need to add the Lib file directory in Properties>Linker>General>Additional Library Directories and add Lib file in Properties>Linker>Input>Additional Dependencies.
Please refer to the document: Use the functionality from the static library in the app.
I am looking for the source of the error since a few hours without success. My project consists of two sub projects. The first one is a dll and the second one is an application (exe).
I simplified my original code, which is part of the dll:
#ifndef blub_base
#define blub_base
#include "SomeInterface.hpp"
#include "Object.hpp"
#include <map>
namespace a
{
namespace b
{
class __declspec(dllexport) CBase : public CSomeInterface
{
protected:
CBase() {}
public:
CBase(SomeDifferentObject* f_object_p) { /* concrete implementation in cpp */ }
~CBase() { /* concrete implementation in cpp */ }
bool initialize() { /* concrete implementation in cpp */ }
bool shutdown() { /* concrete implementation in cpp */ }
void foo() { /* concrete implementation in cpp */ }
virtual void blubblub(Object* f_object_p) { /* concrete implementation in cpp */ }
protected:
bool blub1(Object* f_object_p, std::map<uint32_t, Object*>& f_something_rmap) const { /* concrete implementation in cpp */ }
bool blub2(Object* f_object_p, std::map<uint32_t, Object*>& f_something_rmap) const { /* concrete implementation in cpp */ }
void blub3(Object* f_object_p) const { /* concrete implementation in cpp */ }
};
}
}
#endif
#ifndef blub
#define blub
#include "Base.hpp"
namespace a
{
namespace b
{
class __declspec(dllexport) CChild : public CBase
{
private:
CChild() {}
public:
CChild(SomeDifferentObject* f_object_p) { /* concrete implementation in cpp */ }
/// deconstructor
~CChild() { /* concrete implementation in cpp */ }
void blubblub(Object* f_object_p) override { /* concrete implementation in cpp */ }
protected:
bool blub1(Object* f_object_p, std::map<uint32_t, Object*>& f_something_rmap) const override { /* concrete implementation in cpp */ }
bool blub2(Object* f_object_p, std::map<uint32_t, Object*>& f_something_rmap) const override { /* concrete implementation in cpp */ }
void blub3(Object* f_object_p) const override { /* concrete implementation in cpp */ }
};
}
}
#endif
If I am trying to instantiate a CChild object in my application I get linker errors for all functions of the CChild class:
Error 75 error LNK2001: unresolved external symbol "public: virtual void __thiscall a::b::CChild::blubblub(class a::b::Object *)" (?blubblub#CChild#b#a##UAEXPAVObject#23##Z) application.obj Application
Error 74 error LNK2019: unresolved external symbol "public: virtual __thiscall a::b::CChild::~CChild(void)" (??1CChild#b#a##UAE#XZ) referenced in function "public: virtual void * __thiscall a::b::CChild::`vector deleting destructor'(unsigned int)" (??_ECChild#b#a##UAEPAXI#Z) Application.obj Application
Error 73 error LNK2019: unresolved external symbol "public: __thiscall a::b::CChild::CChild(class a::b::SomeDifferentObject *)" (??0CChild#b#a##QAE#PAVSomeDifferentObject#12##Z) referenced in function _main Application.obj Application
Error 77 error LNK2001: unresolved external symbol "protected: virtual bool __thiscall a::b::CChild::blub1(class Object *,class std::map,class std::allocator > > &)const " (?blub1#CChild#b#a##MBE_NPAVObject#23#AAV?$map#KIU?$less#K#std##V?$allocator#U?$pair#$$CBKI#std###2##std###Z) Application.obj Application
Error 76 error LNK2001: unresolved external symbol "protected: virtual bool __thiscall a::b::CChild::blub2(class Object *,class std::map,class std::allocator > > &)const " (?blub2#CChild#b#a##MBE_NPAVObject#23#AAV?$map#KIU?$less#K#std##V?$allocator#U?$pair#$$CBKI#std###2##std###Z) Application.obj Application
Error 78 error LNK2001: unresolved external symbol "protected: virtual void __thiscall a::b::CChild::blub3(class a::b::Object *)const " (?blub3#CChild#b#a##MBEXPAVObject#23##Z) Application.obj Application
I am using Visual Studio and all cpp files are in the project (checked many times). Each function is implemented e.g.
CChild::CChild(SomeDifferentObject* f_object_p) : CBase(f_object_p)
{
}
It seems that the relevant cpp files are not found?!
Thank you very much for your help!
Kind regards,
Bobby
It is not working because classes are always exported. They need to be exported by dll project and imported by projects that use that dll.
To fix this, add header file, for example ab_dll.h and there:
#ifdef AB_DLL_EXPORT
#define AB_DLL_API __declspec(dllexport)
#else
#define AB_DLL_API __declspec(dllimport)
#endif
Then use that macro in your classes:
class AB_DLL_API CBase : public CSomeInterface
{
//...
};
class AB_DLL_API CChild : public CBase
{
//...
};
Also in your VS dll project add AB_DLL_EXPORT in PreprocessorDefinitions so that the classes are exported. This works that way that if AB_DLL_EXPORT is defined in the project then classes will be exported, otherwise will be imported.
When I attempted to specialize one of my template functions, Visual Studio threw me an external error, including an error for a function that was not specialized.
The three errors:
1>------ Build started: Project: Project3, Configuration: Debug Win32 ------
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall linearList<class FriendToken>::reverse(void)" (?reverse#?$linearList#VFriendToken####UAEXXZ)
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall linearList<class FriendToken>::print(void)" (?print#?$linearList#VFriendToken####UAEXXZ)
1>main.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall linearList<class FriendToken>::insertionSort(void)" (?insertionSort#?$linearList#VFriendToken####UAEXXZ)
Here is the relevant part of the code:
template<class T>
class arrayList : public linearList<T>
{
public:
//other methods
void reverse();
void print();
void insertionSort();
};
template<class T>
void arrayList<T>::reverse()
{
//method body
}
template<>
void arrayList<FriendToken>::insertionSort()
{
//method body
}
template<>
void arrayList<FriendToken>::print()
{
//method body
}
template<class T>
void arrayList<T>::insertionSort(){}
template<class T>
void arrayList<T>::print(){}
Your example shows specializations of the arrayList member functions which I assume are supposed to be overriding their virtual equivalants in linearList. The linker is saying it cant find the virtual members in the class linearList which is not included in your example.
virtual void __thiscall linearList<class FriendToken>::reverse(void)
If I add a definition of linearList like this the linker is quiet (on MSVC2010, I also added a empty FriendToken class to make things work).
template<typename T>
class linearList
{
public:
virtual void reverse() = 0; //pure virtual
virtual void print() = 0;
virtual void insertionSort() = 0;
};
If this is not your problem please post the code for linearList and I will update my answer as that is surely the source of your problem.
If needed for reference here is how I used the function reverse to test:
arrayList<FriendToken> a;
static_cast<linearList<FriendToken>&>(a).reverse();
Please have a look at the following code
Main.cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
system("pause");
return 0;
}
Magic.h
#pragma once
class Magic
{
public:
Magic();
~Magic();
virtual void display()=0;
};
Spell.h
#pragma once
#include "Magic.h"
#include <iostream>
#include <string>
using namespace std;
class Spell :
public Magic
{
public:
Spell(void);
Spell(string words);
~Spell(void);
void display();
private:
string words;
};
Spell.cpp
#include "Spell.h"
#include "Magic.h"
#include <iostream>
#include <string>
using namespace std;
Spell::Spell(void)
{
}
Spell::Spell(string words)
{
this->words = words;
}
Spell::~Spell(void)
{
cout << "Delete Spell" << endl;
}
void Spell::display()
{
cout << "Spell Words: " << words << endl;
}
Here, I am getting the error
1>------ Build started: Project: Revision1_1, Configuration: Debug Win32 ------
1>Spell.obj : error LNK2019: unresolved external symbol "public: __thiscall Magic::~Magic(void)" (??1Magic##QAE#XZ) referenced in function __unwindfunclet$??0Spell##QAE#XZ$0
1>Spell.obj : error LNK2019: unresolved external symbol "public: __thiscall Magic::Magic(void)" (??0Magic##QAE#XZ) referenced in function "public: __thiscall Spell::Spell(void)" (??0Spell##QAE#XZ)
1>C:\Users\yohan\Documents\Visual Studio 2010\Projects\Revision1_1\Debug\Revision1_1.exe : fatal error LNK1120: 2 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I do not understand what to do here. Why is this happening? Please help! I am new to C++ anyway..
Magic is not implementing its constructor and destructor (which also should be virtual).
Don't even declare the constructor if not necessary, e.g.
class Magic {
public:
virtual ~Magic() {}
virtual void display() = 0;
};
Unrelated: I didn't know you can display magic.
You didn't implement
Magic();
~Magic();
You'll need to either implement them inline, in an implementation file, or mark them = default.
You have declared a destructor in your Magic class but did not define it. That's why the linker complains (and the compiler doesn't).
You don't have an implementation for Magic. If your intention is for Magic to be an abstract base class, then just change its declaration to:
#pragma once
class Magic
{
public:
virtual void display()=0;
};
Remember, any method that is not followed by = 0 in the interface must be implemented in the class.
class CommandManager {
public:
void sendText(std::string command);
static bool CommandManager::started;
private:
bool parseCommand(std::string commands);
void changeSpeed(std::vector<std::string> vec);
void help(std::vector<std::string> vec);
};
And here's the client code:
CommandManager::started = true;
Linking these two files together I get:
1>UAlbertaBotModule.obj : error LNK2001: unresolved external symbol "public: static bool CommandManager::started" (?started#CommandManager##2_NA)
1>C:\Development\School\cmput350-uofabot\UAlbertaBot\vs2008\Release\UAlbertaBot.dll : fatal error LNK1120: 1 unresolved externals
Where did I go wrong here?
You're doing that incorrectly.
class CommandManager {
public:
void sendText(std::string command);
static bool started; //NOT this -> bool CommandManager::started
//...
};
then put the definition of static member in .cpp file as:
#include "CommandManager.h" //or whatever it is
bool CommandManager::started = true; //you must do this in .cpp file
Now you can use CommandManager::started in your client code.
You should have inside your class:
class CommandManager {
public:
void sendText(std::string command);
static bool started;
//// etc
};
and outside your class, in a *.cc file (not in a *.hh header file), a definition like
bool CommandManager::started;
BTW, I believe you'll better make that private.
Consider putting
bool CommandManager::started;
where you define other members.