Access static variable from static function [duplicate] - c++

This question already has answers here:
Unresolved external symbol on static class members
(6 answers)
Closed 10 years ago.
It is very important that my function is static, I need to access and modify another static/non-static class member in order to print it out later. How can I do that?
Flow
Class is initiated
Constructor sets variable to something using internal function that must be static
Some time later I print that variable
Example code
#include <iostream>
class MyClass
{
public:
static int s;
static void set()
{
MyClass::s = 5;
}
int get()
{
return MyClass::s;
}
MyClass()
{
this->set();
}
};
void main()
{
auto a = new MyClass();
a->set(); // Error
std::cout << a->get() << std::endl; // Error
system("pause");
}
Error
LNK2001: unresolved external symbol "public: static int MyClass::s" (?s#MyClass##2HA)
LNK1120: 1 unresolved externals

You have declared your static variable, but you have not defined it.
Non-static member variables are created and destroyed as the containing object is created and destroyed.
Static members, however, need to be created independently of object creation.
Add this code to create the int MyClass::s:
int MyClass::s;
Addendum:
C++17 adds inline variables, allowing you code to work with a smaller change:
static inline int s; // You can also assign it an initial value here
^^^^^^

Related

Why does declaring a struct inside another header file cause a LNK2001 error? [duplicate]

This question already has answers here:
static variable link error [duplicate]
(2 answers)
Closed 2 years ago.
I'm trying to make a text-based console video game in c++.
I have an Inventory class with a header and a source file. In the same header file I have declared a struct called STRINGSIZES with two integer members called name and description. They are used to store the length that should be used when displaying the Items, or from which length the name will be shortened. The header file "Inventory.h" looks something like this:
#pragma once
#include <iostream>
struct STRINGSIZES { //the fixed Size with which Inventory lists will be printed
int name;
int description;
};
class Inventory
{
public:
//some unrelated code
Inventory();
static void setStringSizes(int name, int description);
private:
static STRINGSIZES stringSizes;
};
In the Inventory.cpp file, I define the setStringSizes() method like so:
void Inventory::setStringSizes(int name, int description)
{
stringSizes.name = name;
stringSizes.description = description;
}
In my main Source.cpp file, I am firstly calling this method.
Now when I try to compile this I get the errors:
1>Inventory.obj : error LNK2001: unresolved external symbol "public: static int stringSizeNames::name" (?name#stringSizeNames##2HA)
1>Inventory.obj : error LNK2001: unresolved external symbol "public: static int stringSizeNames::description" (?description#stringSizeNames##2HA)
What is the problem here?
The error message refers to a variable which declaration you did not show in the question. But I think it is the same problem as with the static data member stringSizes.
Within the class definition this data member
static STRINGSIZES stringSizes;
is a declaration that is not a definition.
You have to define it outside the class definition in the cpp file for example like
STRINGSIZES Inventory::stringSizes;
If your compiler supports the C++17 Standard then you could define the data member inside the class definition the following way
class Inventory
{
//...
inline static STRINGSIZES stringSizes = {};
};

Unresolved External Symbol calling inherited class function [duplicate]

This question already has answers here:
C++ inlining class methods causes undefined reference
(3 answers)
When should I write the keyword 'inline' for a function/method?
(16 answers)
Closed 2 years ago.
I'm trying to have a class call a function from an inherited class however whenever I do I get an unresolved external error LNK2019. I'm confused to why this is happening as all of the files appear to be properly included, I haven't overridden the function & Visual Studio doesn't complain about it prior to compiling.
I've tried:
Running the replacing the function call with the actual code, this fixes one of the two errors but I still get an unresolved external as the functions in question are calling another function from another class.
Messing around with namespaces, as the inherited class is under a separate namespace I thought that was the problem e.g. Memory::Allocate(...).
Directly calling the class function, so instead of Allocate(...) I tried Memory::GlobalMemoryUser::Allocate(...)
Calling the function using this->...
Relevant code from GlobalMemoryUser.h
#include "MemoryManager"
namespace Memory
{
namespace Internal
{
extern MemoryManager* GlobalMemoryManager;
{
class GlobalMemoryUser
{
public:
// Allocator and deallocator
inline const void* Allocate(size_t, const char* user);
inline const void DeAllocate(void*);
private:
// A pointer to the global memory manager
Internal::MemoryManager* GlobalMemoryManager;
};
}
Relevant code from GlobalMemoryManager.cpp
#include "GlobalMemoryUser.h"
namespace Memory {
const void* GlobalMemoryUser::Allocate(size_t size, const char* user)
{
return GlobalMemoryManager->Allocate(size, user);
}
const void GlobalMemoryUser::DeAllocate(void* p)
{
GlobalMemoryManager->DeAllocate(p);
}
}
Relevant code from System Manager.h
#include "GlobalMemoryUser.h"
namespace ECS
{
class SystemManager : public Memory::GlobalMemoryUser
{
// Constructor and Deconstructor
SystemManager();
~SystemManager();
};
}
Relevant code from SystemManager.cpp
#include "SystemManager.h"
namespace ECS
{
SystemManager::SystemManager()
{
systemAllocator = new Memory::LinearAllocator(ECS_SYSTEM_MEMORYBUFFERSIZE, Allocate(ECS_SYSTEM_MEMORYBUFFERSIZE, "SystemManager"));
}
SystemManager::~SystemManager()
{
for (std::vector<ISystem*>::reverse_iterator it = systemWorkOrder.rbegin(); it != systemWorkOrder.rend(); it++)
{
(*it)->~ISystem();
*it = nullptr;
}
systemWorkOrder.clear();
systemsTable.clear();
DeAllocate((void*)systemAllocator->GetUsedMemoryStart());
delete systemAllocator;
systemAllocator = nullptr;
}
}
The errors in question happen within the constructor and deconstructor for the system manager when trying to call the allocator and deallocator from the GlobalMemoryUser parent class.
Exact Error Message:
LNK2019 unresolved external symbol "public: void const * __cdecl Memory::GlobalMemoryUser::Allocate(unsigned __int64,char const *)" (?Allocate#GlobalMemoryUser#Memory##QEAAPEBX_KPEBD#Z) referenced in function "public: __cdecl ECS::SystemManager::SystemManager(void)" (??0SystemManager#ECS##QEAA#XZ)

Why can't static member methods access its non-static method in C++? [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 3 years ago.
I had to make a callback interface for a new module while I work, so I made a static method in a class.
One thing I still don't understand is why I can't call a non-static member method in a static member like this :
class CAdapterUser
{
public:
CAdapterUser() {}
virtual ~CAdapterUser() {}
void Test();
void Test2();
protected:
CAdapter m_Adapter;
unsigned char buffer[16];
static void TestFunc(void* apContext);
};
void
CAdapterUser::TestFunc( void* apContext )
{
// CAdapterUser* pUser = (CAdapterUser*)apContext;
CAdapterUser* pUser = reinterpret_cast<CAdapterUser*>(apContext);
pUser->Test2(); // Compile error : LNK2019
pUser->buffer[0] = 1; // Even though I can access protected member variable?
}
Could someone answer my question?
LNK2019 is unresolved symbol, probably you simply forgot to implement Test2().

singleton in c++ compile error [duplicate]

This question already has answers here:
Undefined reference to static class member
(9 answers)
Closed 7 years ago.
I tried to make the following singleton class in C++
#pragma once
#include "stdafx.h"
#include <iostream>
class God
{
private:
static God* firstObject;
God()
{
if (firstObject != NULL)
firstObject = this;
}
public:
static God* BuildGod()
{
if (firstObject != NULL)
return firstObject;
else {
God();
return firstObject;
}
}
};
and then use it like so
God* a = God::BuildGod();
Unfortunatley, it won't even compile and it returned the following errors:
LNK2001 unresolved external symbol "private: static class God * God::firstObject" (?firstObject#God##0PAV1#A)
LNK1120 1 unresolved externals
You actually have a worse problem than the build error, because you create a temporary object, and save a pointer to it to be used.
The statement
God();
creates a temporary object, and in the constructor you save a pointer to this temporary object in firstObject which you then return. Using that pointer will then lead to undefined behavior.
One of the usual ways of creating a singleton in C++ would be something like this:
class God
{
public:
static God& get_instance() {
{
static God instance; // This is THE instance
return instance;
}
private:
God() {}
};
A static member of a class has to be defined outside the class, like
class God
{
...
};
God* God::firstObj;
Just beware that having the definition in a header file and including it mamy times calls for trouble.

c++ copy struct unresolved link [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 9 years ago.
I am working on a date wrapper class in c++
I want to copy the tm structure to another structure, but it throws unresolved external link
Error 2 error LNK2001: unresolved external symbol "public: static struct tm * DateUtils::generateDateTimeStruct" (?generateDateTimeStruct#DateUtils##2PAUtm##A)
class DateUtils
{
public:
DateUtils()
{
}
static int getTodaysDate();
static tm * myDateTime;
static void generateDateTimeStruct();
};
tm* DateUtils::myDateTime = NULL;
int DateUtils::getTodaysDate()
{
// If i comment the calling, it does not throws an error
generateDateTimeStruct();
return DateUtils::myDateTime->tm_hour;
}
static void generateDateTimeStruct(){
time_t now = time(0);
static tm s;
now = time(NULL);
localtime_s(&s, &now);
DateUtils::myDateTime = &s;
}
You need to define this member outside the class declaration (in some .cpp file):
tm* DateUtils::myDateTime = NULL;
Note that prefixing with the name of the class is used while defining the other members as well:
In the class declaration:
static int getTodaysDate();
static void generateDateTimeStruct();
but the definition outside the class:
int DateUtils::getTodaysDate() { ... }
void DateUtils::generateDateTimeStruct() { ... }
As myDateTime has been declared to have static storage, you need to assign some memory to it.
The normal thing to do is to define it in exactly one compilation unit; typically in a source file:
tm* Wrapper::myDateTime = NULL;
You have to define the static data member. It was only declared in the class definition but not defined outside the class. In some code module write
tm * Wrapper::myDateTime;
You declare a member function, but define a non-member function with the same name. Change the definition to
static void DateUtils::generateDateTimeStruct(){
// your code here
}
Alternatively, don't define a class at all - it seems just to be somewhere to put static functions, in which case a namespace would be more appropriate.