简体   繁体   中英

Undefined constructor in inherited templated singleton class c++

I ran into a problem today, using a tool I have made some times ago : a Singleton templated class.

template <class C>
class Singleton {
    /*! \class Singleton
    * \brief Singleton Template
    */
public:
    /*!
    * \brief Public access interface
    * \return Singleton instance
    */
    static C *getInstance (){
        // Create new instance if not initialised
        if (_singleton == NULL){
            _singleton = new C;
        }
        return (static_cast<C*> (_singleton));
    }

    /*!
    * \brief Public access destructor
    */
    static void kill(){
        // Clean Singleton object and free memory
        if (_singleton != NULL){
            delete _singleton;
            _singleton = NULL;
        }
    }
protected:
    /*!
     * \brief Empty constructor
     */
    Singleton() = default;
    /*!
     * \brief Destructor
     */
    virtual ~Singleton() = default;

private:
    static C *_singleton; /*!< Unique instance */
};

template <class C>
C *Singleton<C>::_singleton = NULL;

The problem arise when i try to call TextureManager::getInstance() on the (very basic) inherited class which is the following :

class TextureManager : public Singleton<TextureManager> {
    friend class Singleton<TextureManager>;
    /*! \class TextureManager
    * \brief Textures Container
    */
public:
protected:
    /*!
     * \brief Empty constructor
     */
    TextureManager();
    /*!
     * \brief Destructor
     */
    ~TextureManager() override;
private:
};

During compilation, the linker shows me an error that i understand but I do not really understand the reason :

build/main.o: In function `Singleton<TextureManager>::getInstance()':
main.cpp (.text._ZN9SingletonI14TextureManagerE11getInstanceEv[_ZN9SingletonI14TextureManagerE11getInstanceEv]+0x24): undefined reference to `TextureManager::TextureManager()'

It seems that it can't find the definition of the constructor which is in TextureManager.cpp

TextureManager::TextureManager() = default;
TextureManager::~TextureManager() = default;

This code worked on an older project I compiled using premake so my guess is that my current makefile is rubbish but i can't find why...

INCLUDE = -I/usr/X11R6/include/
LIBDIR  = -L/usr/X11R6/lib

SRCDIR := sources
BUILDDIR := build
TARGET := bin/game

SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))

FLAGS = -std=c++11 -Wall
CC = g++
CFLAGS = $(FLAGS) $(INCLUDE)
LIBS =  -lglut -lGL -lGLU -lGLEW -lm

$(TARGET): $(OBJECTS)
    @echo "Linking..."
    @echo "$(CC) $(CFLAGS) $^ -o $@ $(LIBDIR) $< $(LIBS)"; $(CC) $(CFLAGS) -o $@ $(LIBDIR) $< $(LIBS)

$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
    @mkdir -p $(@D)
    @echo "$(CC) $(CFLAGS) -o $@ $(LIBDIR) $< $(LIBS)"; $(CC) $(CFLAGS) -c -o $@ $(LIBDIR) $< $(LIBS)

clean:
    @echo "Cleaning..."
    @echo "$(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)

.PHONY: clean

Now stuck for hours, all my hopes are on you :p

Edit : full make output

g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/main.o -L/usr/X11R6/lib sources/main.cpp -lglut -lGL -lGLU -lGLEW -lm
g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/Tools/ThreadManager.o -L/usr/X11R6/lib sources/Tools/ThreadManager.cpp -lglut -lGL -lGLU -lGLEW -lm
g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/Graphics/GraphicalEngine.o -L/usr/X11R6/lib sources/Graphics/GraphicalEngine.cpp -lglut -lGL -lGLU -lGLEW -lm
g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/Graphics/TextureManager.o -L/usr/X11R6/lib sources/Graphics/TextureManager.cpp -lglut -lGL -lGLU -lGLEW -lm
Linking...
g++ -std=c++11 -Wall -I/usr/X11R6/include/ build/main.o build/Tools/ThreadManager.o build/Graphics/GraphicalEngine.o build/Graphics/TextureManager.o -o bin/game -L/usr/X11R6/lib build/main.o -lglut -lGL -lGLU -lGLEW -lm
build/main.o: In function `Singleton<TextureManager>::getInstance()':
main.cpp:(.text._ZN9SingletonI14TextureManagerE11getInstanceEv[_ZN9SingletonI14TextureManagerE11getInstanceEv]+0x24): undefined reference to `TextureManager::TextureManager()'
collect2: error: ld returned 1 exit status
makefile:18: recipe for target 'bin/game' failed
make: *** [bin/game] Error 1

The problem is that you are only using the first dependency in the $(TARGET) rule:

$(CC) $(CFLAGS) -o $@ $(LIBDIR) $< $(LIBS)
#                               ^^

My comment was actually wrong because you have a different command between the @echo and the actual command:

@echo "$(CC) $(CFLAGS) $^ -o $@ $(LIBDIR) $< $(LIBS)"
#                      ^^                 ^^

I do not see a point in adding this echo line here, I would do as follow:

$(TARGET): $(OBJECTS)
    @echo "Linking..."
    $(CC) $(CFLAGS) $^ -o $@ $(LIBDIR) $(LIBS)
    #               ^^

Had you done so, you would have seen your error sooner I think.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM