c++ link error if function is implemented in .cpp - c++

If I implement the create method of the class in .cpp I get
error LNK2019: unresolved external symbol "protected: __thiscall Singleton::Singleton(void)" (??0Singleton##IAE#XZ) referenced in function "public: static void __cdecl Singleton::create(void)" (?create#Singleton##SAXXZ
However if I implement the method inside the header file it compiles without any error :S
header file
#pragma once
#include <iostream>
class Singleton
{
public:
static Singleton * getInstance()
{
return s_instance;
}
static void create();
static void destroy();
void help();
protected:
static Singleton * s_instance;
Singleton();
};
source file:
#include "Singleton.h"
Singleton * Singleton::s_instance = NULL;
void Singleton::create()
{
if (!s_instance)
{
s_instance = new Singleton;
}
}
void Singleton::destroy()
{
delete s_instance;
s_instance = NULL;
}
However If I implement the create method inside the header it does not throws any error
Header file with create method implemented in it
#pragma once
#include <iostream>
class Singleton
{
public:
static Singleton * getInstance()
{
return s_instance;
}
static void create(){
if (!s_instance)
{
s_instance = new Singleton;
}
}
static void destroy();
protected:
static Singleton * s_instance;
Singleton();
};

In cpp, your create function is trying to initialize Singleton, by using new operator, but you dont give it an constructor. Try to give an implementation to Singleton(). i.e.:
protected:
static Singleton * s_instance;
Singleton() {}
};

The problem.
You have declared a default constructor, and you're using it (in a new expression), but you haven't implemented it.
Fix.
Simply remove the constructor declaration:
protected:
static Singleton * s_instance;
// Singleton(); -- don't have this. Remove it.
};
Other matters.
With protected features the class is designed for inheritance, so how does one ensure that a derived class can only be instantiated via the singleton machinery?
Well you don't have much control over derived classes, so the easiest is just to document that each derived class should declare and define a non-public default constructor.
However, there is a trick that can be used to enforce this, based on the fact that a virtual base must be initialized by the most derived class. This can be used to force client code to add a final class derivation at bottom. Where that most derived class is a template instantiation, which defines a non-public constructor.
A more practical alternative is to turn things upside-down.
That is, instead of designing the Singleton class for derivation (signalled by protected stuff), design it to inherit from a client code class. Again this means using templates. Andrei Alexandrescu discussed a number of singleton approaches using this idea, in his classic book “Modern C++ Design”.

Related

using singleton class to be reached from all classes

I have a weird question. It is so weird it is probably quite easy to solve.
I created a software and I need to implement a class Sing with an sing objeect that must be reached from all classes from the software. Therefore I created it as singleton object in the main function.
My problem is, how can the object sing be reached from other classes (like ClassA) without creating pointers which are handovered by a pointer to every single class in the code.
All the class definition is located in the sing.h file. If I put the definition into the sing.cpp file the compiler will fail.
I managed to create this sing object, but it is not visible from ClassA. How can the object sing be seen without handing over pointers to the constructors of each class?
sing.h file:
#ifndef _SING_H_
#define _SING_H_
//declaration
class Singleton
{
public:
static Singleton* Instance();
static Singleton* InstanceSlave();
int a;
int setTest(int);
protected:
Singleton(){}
private:
static Singleton* _instance;
static Singleton* _instanceSlave;
};
//definitions (only work in header file, not in .cpp file
Singleton* Singleton::_instance =0;
Singleton* Singleton::Instance()
{
if (_instance == 0 )
{
_instance = new Singleton;
}
return _instance;
}
int Singleton::setTest(int b)
{
return 1;
}
#endif _CONF_H_
main.cpp file:
int main()
{
Singleton* sing = sing->Instance();
sing->setTest(2);
ClassA* classa = new ClassA();
}
main.h file:
#inlucde <iostream>
#include "sing.h"
#include "classA.h"
inside the ClassA I would like to have something like this:
classA.h
#inlude sing.h
class classA
{
public:
void doSomeThing(int);
}
classA.cpp:
#include ClassA.h
{
void ClassA::doSomeThing(int a)
{
sing.setTest(a);
}
}
My problem is, how can the object sing be reached from other classes (like ClassA) without creating pointers which are handovered by a pointer to every single class in the code.
The canonical way is to use Scott Meyer's Singleton and provide a static function like
static Singleton& Instance() {
static Singleton theInstance;
return theInstance;
}
Usage is
Singleton::Instance().setTest(2);
In general the Singleton Pattern isn't really considered a good technique, because the coupling with the rest of the code is too tight. It's better to use interfaces (abstract classes) and pass these around as necessary.
Just use
Singleton::Instance()->setTest(a);

Classes and void pointers

I have the following header:
class MyClass {
private:
static void (*OnRequest)();
static void (*OnReceive)(int numBytes);
public:
MyClass();
static void SetOnReceive(void (*function)(int));
static void SetOnRequest(void (*function)(void));
};
void NonClassFunction();
and the following declaration:
#include "MyClass.h"
MyClass::MyClass() {
...
}
void MyClass::SetOnReceive(void (*function)(int) ) {
OnReceive = function;
}
void MyClass::SetOnRequest( void (*function)(void) ) {
OnRequest = function;
}
void NonClassFunction() {
MyClass::OnRequest();
}
The code compiles fine but I get the following errors when I link:
unresolved symbol MyClass::OnReceive, first referenced in ./src/MyClass.obj
unresolved symbol MyClass::OnRequest, first referenced in ./src/MyClass.obj
I need OnRequest and OnReceive to function like a callback through NonClassFunction(). The NonClassFunction is being called by an interrupt so there is a bit of object oriented mangling going on here. MyClass is designed to be inherited. Ideally I would like OnRequest and OnReceive to be virtual but you cannot make static methods virtual.
Those are linker error, which means the members are not defined. They're only declared.
The pointer members are static members, so they need definition, which is outside the class.
Do this in the .cpp file:
void (*MyClass::OnRequest)();
void (*MyClass::OnReceive)(int);
These are definitions, and what you've written in the class are only declarations.
Note the position of * in the above definitions. A slight mistake such as these:
void (MyClass::*OnRequest)(); //notice the difference
void (MyClass::*OnReceive)(int); //notice the difference
would change the meaning completely! Now these are pointers-to-non-static-member-function. So know the difference and be careful. :-)
These two variables in your header:
static void (*OnRequest)();
static void (*OnReceive)(int numBytes);
Have not been defined.
Define them in your cpp file.
void (*MyClass::OnRequest)();
void (*MyClass::OnReceive)(int);
You provided the declarations of the function pointers, but not the definition. Add this to a single cpp file:
void (*MyClass::OnRequest)();
void (*MyClass::OnReceive)(int);
i asked the same question recently
how-to-send-a-message-to-the-class-that-created-the-object
enemies_array[0].enemy = new Enemy(this,&Game::EnemyEvent);
typedef void (Game::*ChangeFunc)(DWORD &)
Class Enemy
{
private:
ChangeFunc iChange;
Game *pGame;
}:
Enemy(Game *pCreatorGame, ChangeFunc iChangeHandler )
{
iChange = iChangeHandler;
pGame = pCreatorGame;
}
void Enemy::Draw(D3DGraphics& gfx)
{
(pGame->*iChange)(this->dwThreadID);

C++ shared_ptr based singletone what causes link error?

So I try this code:
#ifndef TRANSMITTER_H
#define TRANSMITTER_H
class connector
{
public:
static boost::shared_ptr<connector> Instance(){
if(!instance)
{
instance = boost::shared_ptr<connector>(new connector());
}
return instance;
}
private:
connector(){}
static boost::shared_ptr<connector> instance;
};
#endif //TRANSMITTER_H
But get link error:
Error 3 error LNK2001: unresolved external symbol "private: static class boost::shared_ptr<class connector> connector::instance" (?instance#connector##0V?$shared_ptr#Vconnector###boost##A)
What is wrong with shared_ptr I want to return? Shall I make it function scope static variable?
This
static boost::shared_ptr<connector> instance;
inside your class definition is just a declaration. What you don't seem to have is a definition of it. This definition has be outside of the class definition.
However, you should probably prefer to do this:
class connector
{
public:
connector(connector const&) = delete;
connector& operator=(connector const&) = delete;
static boost::shared_ptr<connector> Instance()
{
static boost::shared_ptr<connector> instance (new connector);
return instance;
}
private:
connector(){}
};
In this case instance is defined as a static function-local object inside your inline function definition of Instance. The nice thing about it is that this kind of initialization is guaranteed to be thread-safe in C++11.
You should define
boost::shared_ptr<connector> connector::instance;
in your *.cpp
This makes linker allocate the memory for this static member in static data area.
You have to define static members outside of the class declaration. Here's what the definition looks like:
boost::shared_ptr<connector> connector::instance;
It should be in a cpp, for you probably transmitter.cpp

namespace in static functions

I want to write a little Singleton class that looks like:
#include <vector>
class Interpreter {
private:
static Interpreter* interInstance;
Interpreter() {}
public:
static Interpreter* getInstance();
~Interpreter() {}
};
Interpreter* Interpreter::interInstance = 0;
Interpreter* Interpreter::getInstance(){
if (!interInstance)
interInstance = new Interpreter();
return interInstance;
}
But this will produce this exception:
multiple definition of `Interpreter::getInstance()
This error can be corrected by wrapping the class and the function in one namespace.
But I don't really understand why I need a namespace.
There is one declaration of getInstance() and one implementation, no?
Move the definition outside the header, in an implementation file, for both the member initialization and the method:
Interpreter.h
class Interpreter {
private:
static Interpreter* interInstance;
Interpreter() {}
public:
static Interpreter* getInstance();
~Interpreter() {}
};
Interpreter.cpp
#include "Interpreter.h"
Interpreter* Interpreter::interInstance = 0;
Interpreter* Interpreter::getInstance(){
if (!interInstance)
interInstance = new Interpreter();
return interInstance;
}
Inside a class or struct definition, static doesn't give symbols internal linkage as it does outside, so you're breaking the one definition rule.
If multiple translation units include a header that contains non-inline methods or define the same symbol, you'll run into multiple definition.

Singleton Inheritance Linker Error

I'm new with C++, and I got this linker error,
LNK2001: unresolved external symbol "private: static class DebugLog Singleton::instance" (?instance#?$Singleton#VDebugLog####0VDebugLog##A)
And here is the problematic codes:
template<typename T>
class Singleton {
public:
static T& getInstance() {
return instance;
}
private:
static T instance;
};
class DebugLog : public Singleton<DebugLog> {
public:
void doNothing() {}
};
void main() {
DebugLog::getInstance().doNothing();
}
Could anybody tell me how I can fix that linker error without losing the Singleton inheritance in DebugLog?
Thank you.
You missed:
template<typename T>
T Singleton<T>::instance;
Insert those lines after your class definition.
In order to initialize a static data-member we must include a formal
definition outside the class, in the global scope.
For more information read this link (Section: Static members)
You need to actually define an instance of the static variable DebugLog Singleton::instance somewhere in your code, you just declared that it exists somewhere, but never actually created it to really exist. The linker is looking for it.
Here's some examples of how to do it right.