I'm developing a C++ solution with Visual Studio 2015.
I have a cpp source file and header file hpp with this declaration.
Header:
#ifndef MyLib__FREEFUNCTIONS__INCLUDE__
#define MyLib__FREEFUNCTIONS__INCLUDE__
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
// Check if 'str' is null, empty or consists only of white-space characters.
inline bool IsNullOrWhiteSpace(string str);
// More functions
[ ... ]
#endif
And Source code:
#include "FreeFunctions.h"
inline bool IsNullOrWhiteSpace(string str)
{
return (str.empty() || (str.find_first_not_of(' ') == string::npos));
}
I use this function in a class:
#include "ConvertToOwnFormat.h"
#include "FreeFunctions.h"
ConvertToOwnFormat::ConvertToOwnFormat()
{
}
ConvertToOwnFormat::~ConvertToOwnFormat()
{
}
vector<Entry> ConvertToOwnFormat::ReadCatalogue(string path)
{
if (!IsNullOrWhiteSpace(path)
{
[ ... ]
}
}
And I get the following error in ConvertToOwnFormat::ReadCatalogue:
Error LNK2019 external symbol "bool __cdecl IsNullOrWhiteSpace(class
std::basic_string,class
std::allocator >)"
(?IsNullOrWhiteSpace##YA_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std###Z)
unresolved referenced by the function "public: class std::vector > __cdecl
ConvertToOwnFormat::ReadCatalogue(class std::basic_string,class std::allocator >)"
(?ReadCatalogue#ConvertToOwnFormat##QEAA?AV?$vector#VEntry##V?$allocator#VEntry###std###std##V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##3##Z) MyProjectLib D:\Fuentes\Repos\MyProject\MyProjectLibConsoleTest\ConsoleMyProjectLib\Lib.lib(ConvertToOwnFormat.obj) 1
You have to put declaration of methods within the header. inline tells to compiler that it should replace call of function with the core of function. So, it need it at compilation time for every unit of compilation which use it
#ifndef MyLib__FREEFUNCTIONS__INCLUDE__
#define MyLib__FREEFUNCTIONS__INCLUDE__
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
// Check if 'str' is null, empty or consists only of white-space characters.
inline bool IsNullOrWhiteSpace(std::string str)
{
return (str.empty() || (str.find_first_not_of(' ') == std::string::npos));
}
// Others functions, prototype, ...
#endif
or remove inline in both source and header files
It's totally out of topic but never put a using namespace inside a header: a header should offer something but should not impose something like namespace. See also "using namespace" in c++ headers
Related
I'm having some troubles making a string utility class that has only static methods. Whenever I use a calling class to use a static method in my string utility class, it compiles with an LNK error, 2019. Any help would be much appreciated.
.h is below,
#pragma once
#include <string>
#include "stdafx.h"
#include <iostream>
using namespace std;
static class StringUtil
{
public:
static string Reverse(string);
// bool Palindrome(string);
// string PigLatin(string);
// string ShortHand(string);
private:
// string CleanUp(string);
};
.cpp file is below,
#include "StdAfx.h"
#include "StringUtil.h"
#include <iostream>
static string Reverse(string phrase)
{
string nphrase = "";
for(int i = phrase.length() - 1; i > 0; i--)
{
nphrase += phrase[i];
}
return nphrase;
}
and below is the calling class.
#include "stdafx.h"
#include <iostream>
#include "StringUtil.h"
void main()
{
cout << "Reversed String: " << StringUtil::Reverse("I like computers!");
}
And when it runs, it shows
Error 5 error LNK2019: unresolved external symbol "public: static class std::basic_string,class std::allocator > __cdecl StringUtil::Reverse(class std::basic_string,class std::allocator >)" (?Reverse#StringUtil##SA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V23##Z) referenced in function "void __cdecl a10_StringUtil(void)" (?a10_StringUtil##YAXXZ) H:\Visual Studio 2010\Projects\Object Oriented C++\Object Oriented C++\Object Oriented C++.obj Object Oriented C++
and
Error 6 error LNK1120: 1 unresolved externals H:\Visual Studio 2010\Projects\Object Oriented C++\Debug\Object Oriented C++.exe 1 1 Object Oriented C++
I feel like this is a very simple problem, but I'm used to programming in Java. I'm trying to teach myself how to code in c++ currently, hence my problem.
First of all in C++ we do not have static classes:
#pragma once
#include <string>
#include "stdafx.h"
#include <iostream>
using namespace std;
class StringUtil
{
public:
static string Reverse(string);
// bool Palindrome(string);
// string PigLatin(string);
// string ShortHand(string);
private:
// string CleanUp(string);
};
Second you forgot the class name StringUtil (owner):
string StringUtil::Reverse(string phrase)
{
string nphrase = "";
for(int i = phrase.length() - 1; i >= 0; i--)
{
nphrase += phrase[i];
}
return nphrase;
}
I hope this helps you :)
static string Reverse(string phrase)
{
...
}
does not define the static member function of the class. It defines a file scoped non-member function. You need to use:
string StringUtil::Reverse(string phrase)
{
...
}
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 6 years ago.
I get this error, but I don't know how to fix it.
I'm using Visual Studio 2013.
code
-----DateUtils.h
#pragma once
#include <string>
class DateUtils
{
public:
DateUtils();
~DateUtils();
static time_t str2time_t(const std::string&, const std::string&);
};
-----ForexUtils32.h
#include <string>
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the FOREXUTILS32_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// FOREXUTILS32_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef FOREXUTILS32_EXPORTS
#define FOREXUTILS32_API __declspec(dllexport)
#else
#define FOREXUTILS32_API __declspec(dllimport)
#endif
// This class is exported from the ForexUtils32.dll
class FOREXUTILS32_API CForexUtils32 {
public:
CForexUtils32(void);
// TODO: add your methods here.
};
extern FOREXUTILS32_API int nForexUtils32;
FOREXUTILS32_API int fnForexUtils32(void);
/******************** Add Begin *************************/
FOREXUTILS32_API time_t str2time(const std::string&, const std::string&);
/******************** Add End *************************/
-------DateUtils.cpp
#include "stdafx.h"
#include "DateUtils.h"
#include <sstream>
#include <iomanip>
using namespace std;
DateUtils::DateUtils()
{
}
DateUtils::~DateUtils()
{
}
time_t str2time_t(const string& datetimeIn, const string& formatIn) {
struct tm tm_time;
// For C++11
istringstream iss(datetimeIn);
iss >> get_time(&tm_time, formatIn.c_str());
time_t time = mktime(&tm_time);
return time;
}
------ForexUtils32.cpp
// ForexUtils32.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "ForexUtils32.h"
#include "DateUtils.h"
// This is an example of an exported variable
FOREXUTILS32_API int nForexUtils32=0;
// This is an example of an exported function.
FOREXUTILS32_API int fnForexUtils32(void)
{
return 42;
}
// This is the constructor of a class that has been exported.
// see ForexUtils32.h for the class definition
CForexUtils32::CForexUtils32()
{
return;
}
/******************** Add Begin *************************/
FOREXUTILS32_API time_t str2time(const std::string& datetime, const std::string& format)
{
time_t t = DateUtils::str2time_t(datetime, format);
return t;
}
/******************** Add End *************************/
Error message:
Error 1 error LNK2019: unresolved external symbol "public: static
__int64 __cdecl DateUtils::str2time_t(class std::basic_string,class
std::allocator > const &,class std::basic_string,class std::allocator > const &)"
(?str2time_t#DateUtils##SA_JABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##0#Z) referenced in function "__int64 __cdecl str2time(class
std::basic_string,class
std::allocator > const &,class std::basic_string,class std::allocator > const &)"
(?str2time##YA_JABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##0#Z) D:\visual
studio
2013\Projects\32bit\ForexUtils32\ForexUtils32\ForexUtils32.obj ForexUtils32
How can i fix this error ?Help me Please(I'm not good at english very much. Thanks)
The first line of the function definition
time_t str2time_t(const string& datetimeIn, const string& formatIn) {
have to be
time_t DateUtils::str2time_t(const string& datetimeIn, const string& formatIn) {
(Add the class name to which the member function belongs)
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"));
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.
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.