-2

I have a static method called getSingleton() in a class called Renderer, which I use as a macro like this:

Renderer.h

#define g_Renderer Renderer::getSingleton()

class Renderer {
private:
    Renderer();
    static Renderer renderer;

public:
    Renderer getSingleton();
};

Renderer.cpp

#include "Renderer.h"
Renderer::Renderer() {}

Renderer Renderer::getSingleton() {
#ifndef CREATED_RENDERER
#define CREATED_RENDERER;
    renderer = Renderer();
#endif // !CREATED_RENDERER

    return renderer;
}

I access the method in main:

Main.cpp

#include "Renderer.h"
int main(){
    
    return 0;
}

But Visual Studio gives me this error:

Main.obj : error LNK2019: unresolved external symbol "public: static class Renderer __cdecl Renderer::getSingleton(void)" (?getSingleton@Renderer@@SA?AV1@XZ) referenced in function main

Why is this? Thanks in advance!

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Where did you *define* the `renderer` instance ? You declare it as static, but there is no definition. What does your reference material say about static class member variables? I also don't understand the nature of why you're doing the static class instance far anyway. Unless there is a good reason otherwise, `getSingleton` should be static, and `static Renderer renderer;` can just reside within that function. – WhozCraig Jul 22 '21 at 00:06
  • 1
    `getSingelton` is not static. – jkb Jul 22 '21 at 00:09
  • Are you sure you've posted the actual code that is generating this error? The error refers to a function referenced in `main`, but the `main` you've posted does not reference any functions, it simply returns zero. Also, are you sure that `Renderer.cpp` is being compiled and linked? – jkb Jul 22 '21 at 00:36
  • 3
    That `#ifdef` doesn't make sense. You seem to be using it as a run-time check, but `#ifdef` happens at compile-time. – interjay Jul 22 '21 at 00:38
  • Exactly what the diagnostic says. You need to define the static member in exactly one place in your source code. It is only declared (not defined) in the class definition. The4 macro hackery you're using does not achieve that (and, as been pointed out, does not make sense). Also, if the `Render::getSingleton()` returns by value, it returns a COPY of the static member every time it is called - a singleton that can be copied to create another object is a contradiction - you need to read up on the concepts better. – Peter Jul 22 '21 at 01:45
  • Obligatory link to the [Meyers singleton](https://stackoverflow.com/a/1008289/12334309) – Nathan Pierson Jul 22 '21 at 03:41

1 Answers1

1

Your getRenderer() method is setup all wrong for what you are trying to do.

For one thing, it is not static.

For another, the static variable is only being declared, not defined anywhere, which is why the linker is complaining. You would need to add this line to Renderer.cpp to actually instantiate the variable:

Renderer Renderer::renderer;

Also, getRenderer() is returning a new Renderer object each time it is called, which is useless for a singleton. The #ifdef is also useless at runtime.

Try something more like this instead:

Renderer.h

#ifndef Renderer_H
#define Renderer_H

#define g_Renderer Renderer::getSingleton()

class Renderer {
private:
    Renderer();
public:
    static Renderer& getSingleton();
};

#endif

Renderer.cpp

#include "Renderer.h"

Renderer::Renderer() {}

Renderer& Renderer::getSingleton() {
    static Renderer instance;
    return instance;
}

Main.cpp

#include "Renderer.h"

int main(){
    // use g_Renderer as needed...
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770