Singleton pattern c++ error - c++

Hi I have implemented a singleton pattern in c++ with the VS2010 and the compiler throw me an error !!
#ifndef __EgEngine__
#define __EgEngine__ 1
#include <esUtil.h>
#include <stdlib.h>
#include <EgGpuManager.h>
class EgEngine
{
public:
EgEngine();
static EgGpuManager GetGpuManager();
~EgEngine();
void EgInit();
private:
EgEngine(const EgEngine &other){};
EgEngine* operator = (const EgEngine &other)const {};
static EgGpuManager GpuManager; // Return this !!
ESContext esContext;
};
#endif
The other class
#ifndef __EgGpuManager__
#define __EgGpuManager__ 1
#include <EgBuffer.h>
#include <EgProgram.h>
class EgGpuManager
{
public:
EgBuffer* GetBuffer();
EgProgram* GetNewProgram();
private:
EgGpuManager();
~EgGpuManager();
EgBuffer buffer;
};
#endif
And when I try to compile I have this error:
1>EgEngine.obj : error LNK2001:
unresolved external symbol "private: static class
EgGpuManager EgEngine::GpuManager" (?GpuManager#EgEngine##0VEgGpuManager##A)
Help me please and thanks.

static EgGpuManager GpuManager; // Return this !! this guy has to be instantiated somewhere in your C++ code.
static class members have to appear in the global scope, so in the C++ file add:
EgGpuManager EgEngine::GpuManager.
By the way, you have a private constructor for EgGpuManager class, which will be a problem in this case because it is created by EgEngine. You're not implementing the singleton correctly. Use a static EgGpuManager *EgGpuManager::Get() method to return an instance, and it will instantiate the class on the first call, then you can do it with a private constructor. Otherwise make them friends.

The line "static EgGpuManager GpuManager;" inside the class declaration of EgEngine is only a declaration: You're saying that this object will exist somewhere. The linker complains that it did not find the object anywhere. To solve this, place an instantiation in one of your source files (in global scope):
EgGpuManager EgEngine::GpuManager;

You must put the instantiation of the singleton object either in the global scope, as suggested by other answers, or in the implementation of GetGpuManager() like this :
EgGpuManager& EgEngine::GetGpuManager()
{
static EgGpuManager GpuManager;
return GpuManager;
}
In this case you need to remove the declaration of GpuManager from the class definition. Also note the & to return a reference, as you certainly don't want to return a copy of the object (that would defeat the purpose of making a singleton). The advantage here is that the object will not be created until GetGpuManager() is called for the first time, whereas all statics in global scope are created when the program starts.

Related

Why the singleton initialization failed (link error) [duplicate]

Very simply put:
I have a class that consists mostly of static public members, so I can group similar functions together that still have to be called from other classes/functions.
Anyway, I have defined two static unsigned char variables in my class public scope, when I try to modify these values in the same class' constructor, I am getting an "unresolved external symbol" error at compilation.
class test
{
public:
static unsigned char X;
static unsigned char Y;
...
test();
};
test::test()
{
X = 1;
Y = 2;
}
I'm new to C++ so go easy on me. Why can't I do this?
If you are using C++ 17 you can just use the inline specifier (see https://stackoverflow.com/a/11711082/55721)
If using older versions of the C++ standard, you must add the definitions to match your declarations of X and Y
unsigned char test::X;
unsigned char test::Y;
somewhere. You might want to also initialize a static member
unsigned char test::X = 4;
and again, you do that in the definition (usually in a CXX file) not in the declaration (which is often in a .H file)
Static data members declarations in the class declaration are not definition of them.
To define them you should do this in the .CPP file to avoid duplicated symbols.
The only data you can declare and define is integral static constants.
(Values of enums can be used as constant values as well)
You might want to rewrite your code as:
class test {
public:
const static unsigned char X = 1;
const static unsigned char Y = 2;
...
test();
};
test::test() {
}
If you want to have ability to modify you static variables (in other words when it is inappropriate to declare them as const), you can separate you code between .H and .CPP in the following way:
.H :
class test {
public:
static unsigned char X;
static unsigned char Y;
...
test();
};
.CPP :
unsigned char test::X = 1;
unsigned char test::Y = 2;
test::test()
{
// constructor is empty.
// We don't initialize static data member here,
// because static data initialization will happen on every constructor call.
}
in my case, I declared one static variable in .h file, like
//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}
and in myClass.cpp, I tried to use this m_nMyVar. It got LINK error like:
error LNK2001: unresolved external symbol "public: static class...
The link error related cpp file looks like:
//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}
So I add below code on the top of myClass.cpp
//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}
then LNK2001 is gone.
Since this is the first SO thread that seemed to come up for me when searching for "unresolved externals with static const members" in general, I'll leave another hint to solve one problem with unresolved externals here:
For me, the thing that I forgot was to mark my class definition __declspec(dllexport), and when called from another class (outside that class's dll's boundaries), I of course got the my unresolved external error.
Still, easy to forget when you're changing an internal helper class to a one accessible from elsewhere, so if you're working in a dynamically linked project, you might as well check that, too.
When we declare a static variable in a class, it is shared by all the objects of that class. As static variables are initialized only once they are never initialized by a constructor. Instead, the static variable should be explicitly initialized outside the class only once using the scope resolution operator (::).
In the below example, static variable counter is a member of the class Demo. Note how it is initialized explicitly outside the class with the initial value = 0.
#include <iostream>
#include <string>
using namespace std;
class Demo{
int var;
static int counter;
public:
Demo(int var):var(var){
cout<<"Counter = "<<counter<<endl;
counter++;
}
};
int Demo::counter = 0; //static variable initialisation
int main()
{
Demo d(2), d1(10),d3(1);
}
Output:
Count = 0
Count = 1
Count = 2
In my case, I was using wrong linking.
It was managed c++ (cli) but with native exporting. I have added to linker -> input -> assembly link resource the dll of the library from which the function is exported. But native c++ linking requires .lib file to "see" implementations in cpp correctly, so for me helped to add the .lib file to linker -> input -> additional dependencies.
[Usually managed code does not use dll export and import, it uses references, but that was unique situation.]

Unresolved external symbol C++

I ahve a problem with a code below:
ProgrammSettings.h
#pragma once
static class ProgrammSettings
{
public:
static int fd;
};
Settings.cpp
#include "ProgrammSettings.h"
static bool LoadSettings()
{
ProgrammSettings::fd = 2; // here error Unresolved symbol!!
return true;
}
What i'm doing wrong?
Thanks!
Unlike instance variables that require only a declaration, static member variabs of the class must also be defined.
Currently, your code contains only a declaration. Add a definition of your static fd variable to a cpp file to fix the error:
int ProgrammSettings::fd;
You need to add the following line to the start of your cpp file
int ProgrammSettings::fd;
Static data members declarations in the class declaration are not definition of them
You have forgot to add the definition to match your declaration of fd.You must explicitly define your class's static data members.

Unresolved external symbol [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is an undefined reference/unresolved external symbol error and how do I fix it?
I'm relatively new to C++ (as you can probably tell by the question) and I've hit a problem. I have two files: Drives.h and Drives.cpp
Drives.h
#pragma once
enum MountMode
{
User,
System,
Both,
Auto
};
class Drive
{
public:
Drive(void);
~Drive(void);
BOOL Mount(MountMode mode);
VOID Unmount(void);
BOOL IsConnected(void);
static char* DeviceName;
static char* DrivePath;
};
class Drives
{
public:
Drives(void);
~Drives(void);
};
and my Drives.cpp:
#include "stdafx.h"
#include "Drives.h"
Drives::Drives(void)
{
Drive USB0; //Error happening here
}
Drives::~Drives(void)
{
}
The error is saying that the Drives class constructor, destructor and IsConnected() are all unresolved externals. I'm not sure what I'm missing since I set this class up like the one on cplusplus.com
Thanks in advance
As the error message says, you have not implemented the constructor and destructor of Drive:
Drive::Drive(void) {
...
}
Drive::~Drive(void) {
...
}
Creating a local variable of class type (as you do in Drive USB0;) will invoke that class' constructor, and the destructor will be invoked at the end of the variable's scope; hence the error.
You should implement the other functions of Drive too - declaring a function in a class declaration is essentially a promise that the function will be implemented somewhere.
Yes, those methods have been declared in the Drive class in your header file, but you haven't actually created a body for these methods.
You must either create a body inline in your header file, create a body in a CPP file, or make sure you are linking with an existing file that defines these methods. Otherwise, the error is right, these methods have not been defined.
An Unresolved External Symbol error usually means you have provided a declaration of a function but not its definition.
In your case, since you declared Drive(void) and ~Drive(void) the compiler removes its defaults and expects your definitions to exist, which they don't, so it throws an error.
As a side note: using void in place of empty parenthesis to mean "This function takes no arguments" is a C-Style definition and should not be used.
Also,do not use #pragma once as a substitute for include guards. It is a Microsoft-Specific construct and is not compatible with other compilers. Use actual include guards instead:
#ifndef CLASS_NAME_H
#define CLASS_NAME_H
//CODE HERE
#endif
In the following code you declare two classes(Drive and Drives), but you provide the implementation only for one (Drives)
#pragma once
enum MountMode
{
User,
System,
Both,
Auto
};
class Drive
{
public:
Drive(void);
~Drive(void);
BOOL Mount(MountMode mode);
VOID Unmount(void);
BOOL IsConnected(void);
static char* DeviceName;
static char* DrivePath;
};
class Drives
{
public:
Drives(void);
~Drives(void);
};
To get rid of the error message, you must include an implementation for Drive's class methods. On way to extend your Drives.cpp so that your code may work looks like this:
#include "stdafx.h"
#include "Drives.h"
//Drive class constructor
Drive::Drive(void)
{
//Add initialization code here. For example:
DeviceName = "Name";
DrivePath = "";
}
//Drive class destructor
Drive::~Drive(void)
{
}
//Also add the implementation for Mount
BOOL Drive::Mount(MountMode mode)
{
//implementation for Mount. For example:
return FALSE;
}
//Also add the implementation for Mount
VOID Drive::Unmount()
{
//implementation for Unmount
}
//Also add the implementation for Mount
BOOL Drive::IsConnected()
{
//implementation for IsConnected.For example:
return FALSE;
}
//Drives class constructor
Drives::Drives(void)
{
Drive USB0; //Error happening here
}
//Drives class destructor
Drives::~Drives(void)
{
}
It is also possible if you copy paste-d the code, that you also have the implementation for the Drive class but you save it in another .cpp file, like Drive.cpp. In that case you should either copy all the implementation methods from the other Drive.cpp file to Drives.cpp. Or you should move the declaration of Drive class from Drives.h to Drive.h. In that case you will have clear separation for classes in different files, which is good, but you will have to include Drive.h in the Drives.h file.

Why won't my C++ program link when my class has static members?

I have a little class called Stuff that I want to store things in. These things are a list of type int. Throughout my code in whatever classes I use I want to be able to access these things inside the Stuff class.
Main.cpp:
#include "Stuff.h"
int main()
{
Stuff::things.push_back(123);
return 0;
}
Stuff.h:
#include <list>
class Stuff
{
public:
static list<int> things;
};
but I get some build errors with this code:
error LNK2001: unresolved external symbol "public: static class std::list<int,class std::allocator<int> > Stuff::things" (?things#Stuff##2V?$list#HV?$allocator#H#std###std##A) Main.obj CSandbox
fatal error LNK1120: 1 unresolved externals C:\Stuff\Projects\CSandbox\Debug\CSandbox.exe CSandbox
I am a C# guy, and I am trying to learn C++ for a side project. I think that I don't understand how C++ treats static members. So please explain what I have got wrong here.
Mentioning a static member in a class declaration is a declaration only. You must include one definition of the static member for the linker to hook everything up properly. Normally you would include something like the following in a Stuff.cpp file:
#include "Stuff.h"
list<int> Stuff::things;
Be sure to include Stuff.cpp in your program along with Main.cpp.
Static data members have to be defined outside class declarations, much like methods.
For example:
class X {
public:
static int i;
};
Must also have the following:
int X::i = 0; // definition outside class declaration
Stuff::things is only declared, but it is not defined.
please use:
// Stuff.cpp
#include "Stuff.h"
std::list<int> Stuff::things;
Added: it is also a good practice to protect your header files against multiple inclusion:
// Stuff.h
#ifndef STUFF_H_
#define STUFF_H_
#include <list>
class Stuff {
public:
static std::list<int> things;
};
#endif
Just For your Information, why this works is that in C++ all global variables (including static global) are created before the execution of the main function begins.
Static member have to be declared in the class but defined in the unit (cpp file) where it is really located.
The only exception is in case the class is template: in this case you have to define the member outside the class, but you have to provide it too with the class declaration, in the header file.

Unresolved external symbol on static class members

Very simply put:
I have a class that consists mostly of static public members, so I can group similar functions together that still have to be called from other classes/functions.
Anyway, I have defined two static unsigned char variables in my class public scope, when I try to modify these values in the same class' constructor, I am getting an "unresolved external symbol" error at compilation.
class test
{
public:
static unsigned char X;
static unsigned char Y;
...
test();
};
test::test()
{
X = 1;
Y = 2;
}
I'm new to C++ so go easy on me. Why can't I do this?
If you are using C++ 17 you can just use the inline specifier (see https://stackoverflow.com/a/11711082/55721)
If using older versions of the C++ standard, you must add the definitions to match your declarations of X and Y
unsigned char test::X;
unsigned char test::Y;
somewhere. You might want to also initialize a static member
unsigned char test::X = 4;
and again, you do that in the definition (usually in a CXX file) not in the declaration (which is often in a .H file)
Static data members declarations in the class declaration are not definition of them.
To define them you should do this in the .CPP file to avoid duplicated symbols.
The only data you can declare and define is integral static constants.
(Values of enums can be used as constant values as well)
You might want to rewrite your code as:
class test {
public:
const static unsigned char X = 1;
const static unsigned char Y = 2;
...
test();
};
test::test() {
}
If you want to have ability to modify you static variables (in other words when it is inappropriate to declare them as const), you can separate you code between .H and .CPP in the following way:
.H :
class test {
public:
static unsigned char X;
static unsigned char Y;
...
test();
};
.CPP :
unsigned char test::X = 1;
unsigned char test::Y = 2;
test::test()
{
// constructor is empty.
// We don't initialize static data member here,
// because static data initialization will happen on every constructor call.
}
in my case, I declared one static variable in .h file, like
//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}
and in myClass.cpp, I tried to use this m_nMyVar. It got LINK error like:
error LNK2001: unresolved external symbol "public: static class...
The link error related cpp file looks like:
//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}
So I add below code on the top of myClass.cpp
//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}
then LNK2001 is gone.
Since this is the first SO thread that seemed to come up for me when searching for "unresolved externals with static const members" in general, I'll leave another hint to solve one problem with unresolved externals here:
For me, the thing that I forgot was to mark my class definition __declspec(dllexport), and when called from another class (outside that class's dll's boundaries), I of course got the my unresolved external error.
Still, easy to forget when you're changing an internal helper class to a one accessible from elsewhere, so if you're working in a dynamically linked project, you might as well check that, too.
When we declare a static variable in a class, it is shared by all the objects of that class. As static variables are initialized only once they are never initialized by a constructor. Instead, the static variable should be explicitly initialized outside the class only once using the scope resolution operator (::).
In the below example, static variable counter is a member of the class Demo. Note how it is initialized explicitly outside the class with the initial value = 0.
#include <iostream>
#include <string>
using namespace std;
class Demo{
int var;
static int counter;
public:
Demo(int var):var(var){
cout<<"Counter = "<<counter<<endl;
counter++;
}
};
int Demo::counter = 0; //static variable initialisation
int main()
{
Demo d(2), d1(10),d3(1);
}
Output:
Count = 0
Count = 1
Count = 2
In my case, I was using wrong linking.
It was managed c++ (cli) but with native exporting. I have added to linker -> input -> assembly link resource the dll of the library from which the function is exported. But native c++ linking requires .lib file to "see" implementations in cpp correctly, so for me helped to add the .lib file to linker -> input -> additional dependencies.
[Usually managed code does not use dll export and import, it uses references, but that was unique situation.]