I'm trying to make a Singleton class in C++ with Xcode. It's a really basic class and I get a linker error that I don't understand. Can any1 help please?
Here is the class header file :
#ifndef _NETWORK_H_
#define _NETWORK_H_
#include <iostream>
#include <list>
#include "Module.h"
using namespace std;
/*
* Assume only one network can run at a time
* in the program. So make the class a singleton.
*/
class Network {
private:
static Network* _instance;
list<Module*> _network;
public:
static Network* instance();
};
#endif
Here is the impl file :
#include "Network.h"
Network* Network::instance() {
if (!_instance)
_instance = new Network();
return _instance;
}
Here is the compiler error :
Undefined symbols for architecture x86_64:
"Network::_instance", referenced from:
Network::instance() in Network.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
You need to declare actual storage for Network::_instance somewhere. Likely the impl. file.
Try adding to your impl file:
Network *Network::_instance=0;
You need to define your instance in the implementation file:
#include "Network.h"
Network *Network::_instance;
The static Network *_instance; declaration just says that there exists a Network::_instance somewhere. You must provide a single definition somewhere for it to actually exist.
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 4 months ago.
The community reviewed whether to reopen this question 4 months ago and left it closed:
Original close reason(s) were not resolved
Defining a class with the template generics is not letting me compile this class.
I have the following three files:
Class Definition:
#ifndef _myclass_h
#define _myclass_h
template <typename ValueType>
class myClass {
public:
myClass();
};
#endif
Class Implementation:
#include "myClass.h"
template <typename ValueType>
myClass<ValueType>::myClass() { }
And the test file:
#include "myClass.h"
int main() {
myClass<int> cls;
return 0;
}
I'm compiling it on a MacBook Air (M1, 2020) running a MacOs Big Sur version 11.6 (20G165).
And when running this command:
g++ -std=c++11 -o testMyClass myClass.cpp testMyClass.cpp
I'm getting this error:
Undefined symbols for architecture arm64:
"myClass<int>::myClass()", referenced from:
_main in testMyClass-595230.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [testMyClass] Error 1
It seems that for some reason the compiler is not able to find the class constructor definition in myClass.cpp. If I take the template header in all of the classes and make the proper adaptations, the class is compiled.
Does anyone have a clue on how to solve that?
I was able to implement the idea suggest here by doing the following.
In myClass.cpp I commented out the inclusion, ending up with:
/* #include "myClass.h" */
template <typename ValueType>
myClass<ValueType>::myClass() { }
And included myClass.cpp to myClass.h, like this (last line):
#ifndef _myclass_h
#define _myclass_h
template <typename ValueType>
class myClass {
public:
myClass();
};
#endif
#include "myClass.cpp"
Aesthetically, I consider this to be an ugly solution, but it works.
I have seen many related questions to this problem, but after carefully following advice from members, my problem still persists. The code is quite simple. I only have the following header file ("instrument.h"), which contains the base class and the template class:
#include <stdio.h>
#include <string>
using namespace std;
class Instrument
{
public:
Instrument();
virtual void print() const = 0;
};
template <class parameter> class Equity : public Instrument
{
public:
Equity();
virtual void print() const;
};
Now, in my main function on main.cpp I only do the following:
#include "instrument.h"
#include <iostream>
int main() {
Equity<double> pb;
return 0;
}
Well, I get the very well-known error:
Undefined symbols for architecture x86_64:
"Equity<double>::Equity()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have already changed in Build Settings the C++ standard library to libstdc++, also to default compiler, and so on. Do I have a problem with my project settings? Is perhaps the template wrongly implemented? I was thinking I should also have a instrument.cpp file, but then again definitions for templates must be kept in the header file so that would probably crash too.
Thanks in advance
You declared the default constructors for both Instrument and Equity but defined them nowhere.
Alter their definitions appropriately:
public:
Equity() = default; // Or {} in pre-C++11
// ^^^^^^^^^
(And equivalently for Instrument)
You can also completely omit the declarations of any default constructors for now since you didn't declare any other constructors in both Equity and Instrument and the default constructors will be generated automatically.
I am trying to create a very classic singleton on C++, Mac OS using Xcode
I create the Class MySingleton as follow:
class MySingleton{
private:
int val;
static MySingleton *instance;
MySingleton(){
val = 0;
}
public:
int getVal(){
return val;
}
void setVal(int iVal){
val = iVal;
}
static MySingleton* getInstance(){
if(instance == NULL)
instance = new MySingleton();
return instance;
}
};
Linker is complaining about static MySingleton* getInstance()
Follow the Linker message:
Undefined symbols for architecture x86_64: "MySingleton::instance",
referenced from:
MySingleton::getInstance() in main.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code
1 (use -v to see invocation)
Could somebody help on this? Perhaps I need to set something on Xcode, which by the way is version 4.2.1, and I am not able in doing this.
Thanks.
You need to define static variable in your cpp file, like this:
MySingleton *MySingleton::instance = 0;
The static member MySingleton needs to be defined in the cpp file. In the header you have have only declared it. See this for more information: Why do static variables need to be declared twice in C++
As far as I can see, you've declared static MySingleton *instance but haven't defined it anywhere.
I am trying to build someone else's code in VS2010. It builds fine in VS2005, but I need to upgrade it.
They have defined a macro as follows in a header:
#include <boost/scoped_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/thread/once.hpp>
#define DEFINE_SINGLETON(name) boost::scoped_ptr<name> Singleton<name>::_instance
template<class T> class Singleton : private boost::noncopyable
{
public:
static T& instance()
{
boost::call_once(init, flag);
return *_instance;
}
static void init()
{
_instance.reset(new T());
}
protected:
Singleton() {}
~Singleton() {}
private:
static boost::scoped_ptr<T> _instance;
static boost::once_flag flag;
};
template<class T> boost::once_flag Singleton<T>::flag = BOOST_ONCE_INIT;
I've managed to get the code to build now, but I am getting lots of linker errors about this macro:
project1.lib(file1.obj) : error LNK2001: unresolved external symbol "private: static class boost::scoped_ptr<class ClassABC> Singleton<class ClassABC>::_instance" (?_instance#?$Singleton#VClassABC####0V?$scoped_ptr#VClassABC###boost##A)
An example of the macro being used (in source file):
#include "singleton.h"
DEFINE_SINGLETON(ClassABC);
I am quite new to Boost and also to templates (sorry), so I cannot fathom why I'm getting these errors when it all linked fine in VS2005. Its worth noting, that in order to do the upgrade we have also had to upgrade our Boost version, so this could be a factor - a few checks already performed:
Header file is included in source file
Boost dir is added to include dirs (under VC++ dirs inproperty pages)
Added boost lib dir to Linker -> General -> Additional library dependencies
For info, I am compiling a Multi-threaded debug dll on Win32.
I have spent most of the day googling to no avail, so any help greatly appreciated!
Many thanks :)
I don't see you used the macro anywhere in the posted code.
You need to use it as:
//add this line after BOOST_ONCE_INIT or before it, or wherever you see fit.
template<class T> DEFINE_SINGLETON(T);
Personally I would prefer this:
template<class T> boost::scoped_ptr<T> Singleton<T>::_instance;
I have a noob question here.
I'm getting my head around the C++ structure and syntax and I've hit a bit of a wall.
I know I am missing something from my concept. So first a little code to help describe the situation.
Control.h
#pragma once
#ifndef CONTROL_H
#define CONTROL_H
class Control
{
public:
Control();
~Control();
private:
public:
};
#endif /*CONTROL_H*/
Control.cpp
#include "Control.h"
#include "Hello.h"
Hello helloObj;
Control::Control()
{
}
Control::~Control()
{
}
int main()
{
int a = helloObj.HelloWorld();
return 0;
}
Hello.h
#pragma once
#ifndef HELLO_H
#define HELLO_H
class Hello
{
public:
Hello();
~Hello();
private:
public:
int HelloWorld(void);
};
#endif /*HELLO_H*/
Hello.cpp
#include "Hello.h"
Hello::Hello()
{
}
Hello::~Hello()
{
}
int HelloWorld()
{
return 5;
}
I try and compile control.cpp with g++ on OSX 10.7 and get
Undefined symbols for architecture x86_64:
"Hello::Hello()", referenced from:
__static_initialization_and_destruction_0(int, int)in cccZHWtd.o
"Hello::~Hello()", referenced from:
___tcf_1 in cccZHWtd.o
"Hello::HelloWorld()", referenced from:
_main in cccZHWtd.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Is it the compiler, my code or my concept of whats going on?
Am I not instantiating something correctly?
Any links describing this in more detail would be appreciated.
Ultimately I want to be able to run a function in another class and return the result...normal OO, keeping your program modular stuff....
The errors you are getting are Linking errors not compilation errors.
The linker is not able to find definitions of the said functions & hence it reports the errors. It seems You have not included the Hello.cpp file containing the function definitions in your project.
Make sure Hello.cpp is included in your project and is a part of your project or
If you are using command line for compilation and linking make sure you have specified Hello.cpp in the file names on the command line.
Most of the issue is me not being familiar as I should be with g++ (Thanks Als).
There were are few syntax issues as well (Thanks Brain).
Here is the corrected (albiet slightly bloated for an overview of stucture) code and g++ command
Control.h
#pragma once
#ifndef CONTROL_H
#define CONTROL_H
class CONTROL
{
private:
//nothing defined yet...
public:
Control(); //default constructor
~Control(); //default destructor
};
#endif /*CONTROL_H*/
Control.cpp
#include "Hello.h"
#include "Control.h"
Hello helloTest; //instantiates the Hello Object
Control::Control()
{
}
Control::~Control()
{
}
int main()
{
helloTest.HelloWorld();
return 0;
}
Hello.h
#pragma once
#ifndef HELLO_H
#define HELLO_H
class Hello
{
private:
//nothing defined yet
public:
Hello(); //default constructor
~Hello(); //default destructor
void HelloWorld();
};
#endif /*HELLO_H*/
Hello.cpp
#include "Hello.h"
#include <iostream> //so we can use 'cout'
using namespace std;
Hello::Hello()
{
}
Hello::~Hello()
{
}
void Hello::HelloWorld()
{
std::cout << "Hello lovelies!\n"; //The magic word.
}
Then we run g++ like so
g++ -o Hello ./Control.cpp ./Hello.cpp
g++ [option] [output file name] [input files]
First of all:
public:
Hello();
~Hello();
private:
public:
is pointless, a class defaults to private, and there is no need to make it
public twice nor do I know if you can do that furthermore if you have no private members private should not be in there (not trying to be mean just some advice :-) )
Now to answer the question (with a guess DISCLAIMER: I AM NOT 100% FAMILIAR WITH GCC):
This is a linker error, it may be there because
the compiler can not find the definition of
HelloWorld(void);.
Let me explain:
In your header file you wrote:
int HelloWorld(void);
However in your .cpp you write:
int HelloWorld()
{
return 5;
}
The function's (or in this case method because it is inside a class)
arguments need to be exactly the same in the header and source, you
can not even change the names (or at least you cant with VC++ which is
what I use; I have little experience with gcc) so this may be resolvable
by typing
int HelloWorld(void)
{
return 5;
}
Next (DISCLAIMER I AM NOT 100% familiar with the pre-proccsor):
You also use the #pragma once pre-proccsor tag, I dont use it but
I believe that means you can only include a file once and you have included Hello.h and Control.h twice, like I said I am no expert in the pre-proccsor but you commented out
HELLO_H
and
CONTROL_H