Unresolved external symbol with custom blocking queue implementation - c++

I have created my own blocking queue and I'm having some trouble figuring out why I get a linker error (note this is a Qt app in Visual Studio 2010):
#ifndef BLOCKING_QUEUE_H
#define BLOCKING_QUEUE_H
#include <QObject>
#include <QSharedPointer>
#include <QWaitCondition>
#include <QMutex>
#include <queue>
namespace TestingNS
{
template<typename Data>
class BlockingQueue
{
private:
std::queue<QSharedPointer<Data>> _queue;
QMutex _mutex;
QWaitCondition _monitor;
volatile bool _closed;
public:
BlockingQueue();
void Close();
size_t Size();
void Empty();
bool IsClosed();
bool Enqueue(QSharedPointer<Data> data);
bool TryDequeue(QSharedPointer<Data>& value, unsigned long time = ULONG_MAX);
};
}
#endif //BLOCKING_QUEUE_H
The implementation is a bit longer, so I have a pastie for it: http://pastie.org/5368660
The program entry point looks like this:
#include <QtCore/QCoreApplication>
#include <QTimer>
#include <iostream>
#include "BlockingQueue.h"
using namespace std;
using namespace TestingNS;
class Item
{
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BlockingQueue<Item> queue;
cout << "Press any key to exit!" << endl;
char in;
cin.get(in);
QTimer::singleShot(0, &a, SLOT(quit()));
return a.exec();
}
The linker error I get is:
Error 1 error LNK2019: unresolved external symbol "public: __thiscall TestingNS::BlockingQueue<class Item>::BlockingQueue<class Item>(void)" (??0?$BlockingQueue#VItem###TestingNS##QAE#XZ) referenced in function _main
I don't understand why the linker can't find the constructor (nor any other method from BlockingQueue). Any ideas?

It's template, you have to put the implementation inside BlockingQueue.h
For a while, the standard did
provide the keyword export to allow such a separate implementation file. But not many
vendors implemented it. C++11 discontinues that use of export but reserves the export
keyword for possible future use.)
Templates have to be used in conjunction with requests for particular
instantiations of templates.

Related

Linker issue in Visual Studio C++

I'm trying to get started with C++ in VS 2017 (empty project template), but immediately ran into linker problems when adding 1 simple class, so I guess I'm missing something important...
My project looks like this:
test.h:
#include <iostream>
class test
{
public:
test();
~test();
std::string getInfo();
};
test.cpp:
#include "test.h"
test::test() {}
test::~test() {}
std::string getInfo() {
return "test";
}
And main.cpp:
#include <iostream>
#include <string>
#include "test.h"
int main(int argc, char **argv) {
test t;
std::cout << "output: " << t.getInfo() << std::endl;
return 0;
}
The linker error I get is the infamous LNK2019:
LNK2019 unresolved external symbol "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl test::getInfo(void)" (?getInfo#test##QEAA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##XZ) referenced in function main
Any ideas what I am doing wrong here?
Thanks!
In file test.cpp you need to properly specify the scope of the member function:
std::string test::getInfo() {
return "test";
}
Note the test:: before the getInfo()

LNK2019 uresolved symbol

I am struggling with
main.obj:-1: error: LNK2019: unresolved external symbol "public: __cdecl Book::Book(void)" (??0Book##QEAA#XZ) referenced in function main
main.obj:-1: error: LNK2019: unresolved external symbol "public: void __cdecl Book::update(class Order)" (?update#Book##QEAAXVOrder###Z) referenced in function main
From what I have read, it usually is because of missing selectors, but I can't see myself missing anything. Also, no static variables, parameters seem correct, ... going through the issue list below didn't help figure out the issue.
https://msdn.microsoft.com/en-us/library/799kze2z.aspx
#include <QCoreApplication>
#include <order.h>
#include <book.h>
#include <iostream>
#include <vector>
std::vector<Order> md_orders;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Order order;
order.setIsBid( true );
order.setSize( 500 );
order.setPrice( 10.00 );
double price = order.getPrice();
Book book;
book.update( order );
std::cout << price;
return a.exec();
}
book.h
#ifndef BOOK_H
#define BOOK_H
//#include <order.h>
#include <vector>
class Book
{
public:
Book();
Order getBest( double, bool );
void update( Order );
double getBestPrice( bool );
private:
std::vector<Order> _orders;
};
#endif // BOOK_H
book.cpp
#include "book.h"
#include <limits>
//#include <order.h>
#include <iostream>
int imax = std::numeric_limits<int>::max();
Book::Book()
{
}
void Book::update( Order order ) {
std::cout << order.getSize();
}
I am new to cpp. I seem to be doing the same with the book class as with the order class, where it works fine. This is very confusing. Any pointers?
So, out of curiosity, I created a new projected and added a class TestA and run it, all went fine. Then I created class TestB exactly the same way and it breaks with the same error for TestB, but not TestA
#include <QCoreApplication>
#include "testa.h"
#include "testb.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
TestA A;
TestB B;
return a.exec();
}
testa.h
#ifndef TESTA_H
#define TESTA_H
class TestA
{
public:
TestA();
};
#endif // TESTA_H
testb.h
#ifndef TESTB_H
#define TESTB_H
class TestB
{
public:
TestB();
};
#endif // TESTB_H
throws this
main.obj:-1: error: LNK2019: unresolved external symbol "public: __cdecl TestB::TestB(void)" (??0TestB##QEAA#XZ) referenced in function main
That is all on qt creator. It just seems very weird behaviour
In your main.cpp,
Notice how you have include book.h
Compiler will not look for book.h in local directory and couldn't find definition of book in standard lib location.
Instead of
#include <book.h> use #include"book.h"
Adding further.
You haven't defined below method in book.cpp and from main function you are trying to access them. Reason for all your pain.
Order getBest( double, bool );
double getBestPrice( bool );
You should do the following (provided you run compiler and linker manually):
Compile main.cpp
Compile book.cpp
Link both files into a single executable
All of above can be done in one command if your compiler allows it.
Since I'm not familiar with MSVC compiler, I'll show how I would do this with gcc:
gcc -c -o main.o main.cpp # Compiles main.cpp into main.o
gcc -c -o book.o book.cpp # Compiles book.cpp into book.o
gcc -o my_app main.o book.o # Creates the my_app executable from main.o and book.o
or
gcc -o my_app main.cpp book.cpp # Does all of above in one command

error LNK2019: unresolved external symbol "public: void __thiscall Button::ButtonInit" [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
I've been going through a C++/SFML tutorial (http://www.gamefromscratch.com/page/Game-From-Scratch-CPP-Edition.aspx) and, having reached the end, started altering the code to try out various things and get more comfortable both with C++ and SFML.
For the menu screen, I decided to create an object for buttons. To this end I created Button.cpp and Button.h, then linked to Button.h in the MainMenu.h file. I added Button button_play as a public member of class MainMenu, however when I call a Button function (for example: button_play.ButtonInit("new-game");), I receive the error: error LNK2019: unresolved external symbol "public: void __thiscall Button::ButtonInit(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?ButtonInit#Button##QAEXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) referenced in function "public: enum MainMenu::MenuResult __thiscall MainMenu::Show(class sf::RenderWindow &)" (?Show#MainMenu##QAE?AW4MenuResult#1#AAVRenderWindow#sf###Z)
I've done a lot of searching around this, and most of the answers I've found revolve around not implementing class member functions correctly, however as far as I can tell I am doing it correctly. I am, however, very new to C++, so it's possible that I'm just missing something.
Here's my code:
MainMenu.h
#pragma once
#include "SFML\Window.hpp"
#include "SFML\Graphics.hpp"
#include "GameObjectManager.h"
#include "Button.h"
#include <list>
class MainMenu
{
public:
MainMenu(){};
~MainMenu() {};
enum MenuResult { Nothing, Exit, Play };
const static GameObjectManager& GetGameObjectManager();
struct MenuItem
{
public:
sf::Rect<int> rect;
MenuResult action;
};
MenuResult Show(sf::RenderWindow& window);
static GameObjectManager _gameObjectManager;
Button button_play;
private:
MenuResult GetMenuResponse(sf::RenderWindow& window);
MenuResult HandleClick(int x, int y);
std::list<MenuItem> _menuItems;
};
MainMenu.cpp (this is quite long; I've only included the function that calls ButtonInit() and the function that Show() returns - if you need to see more, let me know and I can include the rest of the code for this file)
#include "stdafx.h"
#include "MainMenu.h"
#include "ServiceLocator.h"
#include "Button.h"
MainMenu::MenuResult MainMenu::Show(sf::RenderWindow& window)
{
button_play.ButtonInit("new-game");
return GetMenuResponse(window);
}
MainMenu::MenuResult MainMenu::GetMenuResponse(sf::RenderWindow& window)
{
sf::Event menuEvent;
while(42 != 43)
{
while(window.pollEvent(menuEvent))
{
if(menuEvent.type == sf::Event::MouseMoved)
{
button_play.Update(window);
}
if(menuEvent.type == sf::Event::MouseButtonPressed)
{
if(ServiceLocator::GetAudio()->IsSongPlaying())
{
ServiceLocator::GetAudio()->StopAllSounds();
}
return HandleClick(menuEvent.mouseButton.x,menuEvent.mouseButton.y);
}
if(menuEvent.type == sf::Event::Closed)
{
return Exit;
}
}
}
}
Button.h
#pragma once
class Button
{
public:
Button() {};
~Button() {};
void ButtonInit(std::string name);
void Update(sf::RenderWindow & rw);
};
Button.cpp
#include "StdAfx.h"
#include "Button.h"
void Button::ButtonInit(std::string name)
{
}
void Button::Update(sf::RenderWindow & rw)
{
}
stdafx.h (probably don't need to see this, but just in case)
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <map>
#include <iostream>
#include <cassert>
#include <string>
Any help would be appreciated.
I assume, you have both classes in the same project.
The linker-message tells you, that the linker does not find a fitting function definition.
So my guess would be ... the linker cannot find a fitting overload of the function. "new-game" is a const char* and it is not a std::string.
a) change your method signature to
void ButtonInit(const char* name);
or
b) call your method like:
button_play.ButtonInit(std::string("new-game"));

error LNK2005: quest_tree::enter_one(class quest_tree::quest_node * &,class std::basic_string<char,struct std::char_traits<char>

I've seen many posts on LNK2005 error, but decided to ask my own anyway.
Here is the error code:
1>setup_quest_tree.obj : error LNK2005: "private: void __thiscall quest_tree::enter_one(class quest_tree::quest_node * &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?enter_one#quest_tree##AAEXAAPAVquest_node#1#ABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z) already defined in mainFunction.obj
1>setup_quest_tree.obj : error LNK2005: "void __cdecl setup_quest_tree(void)" (?setup_quest_tree##YAXXZ) already defined in mainFunction.obj
1>C:\Users\Timothy\Documents\Visual Studio 2008\Projects\ttbag\Debug\TTBAG.exe : fatal error LNK1169: one or more multiply defined symbols found
I'm trying to get the program to compile but am running into linker errors while doing so, probably because I've included quest_tree.h twice, but when I got rid of one of the declarations of quest_tree.h in setup_quest_tree.cpp I run into this error:
1>c:\users\timothy\documents\visual studio 2008\projects\ttbag\ttbag\setup_quest_tree.cpp(8) : error C2065: 'quest_tree' : undeclared identifier
There are many files so I am only including the ones for my project that are related to the error.
setup_quest_tree.cpp:
#ifndef SETUP_QUEST_NODES_CPP
#define SETUP_QUEST_NODES_CPP
#include <string>
#include "quest_tree.h"
void setup_quest_tree() {
quest_tree quest_tree_obj; //start out with two quest nodes
std::string welcome_message = "debug-welcome message";
quest_tree_obj.enter(welcome_message);
}
#endif
setup_quest_tree.h:
#ifndef SETUP_QUEST_TREE_H
#define SETUP_QUEST_TREE_H
#include "quest_tree.h"
#include "setup_quest_tree.cpp"
//function declarations
void setup_quest_tree (quest_tree &quest_tree_obj);
#endif /* SETUP_QUEST_TREE_H */
mainFunction.cpp (just the include statements):
#define DEBUG_LINES_ON
#include <iostream>
#include <fstream>
#include <time.h>
#include "weather.h"
#include "item.h"
#include "map.h"
#include "person.h"
#include "location.h"
#include "bag.h"
#include "equipped_items.h"
#include "global_vars.h"
#include "setup_quest_tree.h"
int main() { ...
quest_tree.h:
#ifndef QUEST_TREE_H
#define QUEST_TREE_H
#include <string>
#include <cstdlib>
class quest_tree {
private:
// the basic node of the tree. Do way to read from file?
class quest_node {
private:
quest_node *quest_nodes; // pointer to array of quests that activate upon quest activation
public:
//std::string word; // we will replace this with our own data variable
std::string note_to_player; //note that is shown upon quest activation
/*
quest_node(){ // default constructor
note_to_player = "";
}
*/
quest_node(short int num_nodes = 2){
quest_nodes = new quest_node[num_nodes]; // problem: not declared in quest_tree but rather in quest_node
note_to_player = "";
}
friend class quest_tree;
};
// the top of the tree
quest_node * root;
// Enter a new node into the tree or sub-tree
void enter_one(quest_node *&node, const std::string& note_to_player);
public:
quest_tree() {root = NULL;} // constructor
// Add a new note_to_player to our tree
void enter(std::string& note_to_player) {
enter_one(root, note_to_player);
}
};
void quest_tree::enter_one(quest_node *&new_node, const std::string& note_to_player)
{
// see if we have reached the end
if (new_node == NULL) {
new_node = new quest_node;
for (short int index = 0; index < (sizeof(new_node->quest_nodes)/sizeof(new_node->quest_nodes[0])); index++) { // initialize quest_nodes
new_node->quest_nodes[index] = NULL;
}
new_node->note_to_player = note_to_player;
}
if (new_node->note_to_player == note_to_player)
return;
/*
if (new_node->note_to_player < note_to_player)
enter_one(new_node->right, word);
else
enter_one(new_node->left, word)
*/
}
#endif /* QUEST_TREE_H */
You have included the implementation in the setup_quest_tree.h header file
#include "setup_quest_tree.cpp"
and included it in several translation units.
To fix this, at least in setup_quest_tree.cpp just include the declarations from setup_quest_tree.h, and remove that #include "setup_quest_tree.cpp" statement from setup_quest_tree.h should fix your linker errors.
You have to provide exclusively one definition (implementation) for your class (see also this answer for "Is is a good practice to put the definition of C++ classes into the header file?").
If you put it there, just since you don't know how to add the setup_quest_tree.cpp to your program, check this Q&A please to learn more about the linking process.
Here's the relevant section from the current c++ standard
3.2 One definition rule [basic.def.odr]
1 No translation unit shall contain more than one definition of any variable, function, class type, enumeration
type, or template.

C++ "unresolved external symbol" using namespace from different project

I have two projects (call them Test and Intrados). Inside Intrados, I have the following namespace:
#include "Mapper.h"
#include "Director.h"
#include "Driver.h"
#include <iostream>
#include <string>
using namespace std;
namespace IntradosMediator {
void addVehicle(string);
}
void IntradosMediator::addVehicle(string vehicleName) {
Mapper* mapper = Mapper::getInstance();
mapper->addVehicle(vehicleName);
}
From within the Intrados project, calling "IntradosMediator::Mapper(addVehicle)" works just fine; yet, in project Test, the following code produces a link error:
#include "IntradosMediator.cpp"
#include "Mapper.h"
using namespace IntradosMediator;
int main(){
IntradosMediator::addVehicle("Car X");
return 0;
}
The error is:
Test.obj : error LNK2019: unresolved external symbol "public: static class Mapper *
__cdecl Mapper::getInstance(void)" (?getInstance#Mapper##SAPAV1#XZ) referenced in
function "void __cdecl IntradosMediator::addVehicle(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >)"
(?addVehicle#IntradosMediator##YAXV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##
std###Z)
I've made sure to add Intrados as a reference for Test, and also included it in the Include Directories. Not sure what to do here, since I'm new to C++. Thanks in advance for any advice.
Edit:
I'm adding the Mapper code here:
//.h
#ifndef MAPPER_H
#define MAPPER_H
#include <string>
using std::string;
class Mapper {
public:
static Mapper* getInstance();
void addVehicle(string);
private:
//this is a singleton
Mapper(){};
};
#endif
//.cpp
#include "Mapper.h"
#include <vector>
#include <iostream>
#include <string>
using namespace std;
vector<string> vehicleList;
Mapper* Mapper::getInstance(){
static Mapper instance;
return &instance;
}
void
Mapper::addVehicle(string vehicleName) {
vehicleList.push_back(vehicleName);
}
The error says the linker can't find Mapper::getInstance (it seems to find your addVehicle function just fine). Might you be failing to include the library that implements "Mapper" in your link?
Could you paste your code for class Mapper?
It seems like you are missing addVehicle function in that class, which is what the compiler is complaining about.