Adrian H.
Adrian H.

Reputation: 23

How to implement Singleton C++ the right way

I am currently trying to implement a class with the Singleton Pattern in C++. But I get following linking error:

projectgen.cpp:(.bss+0x0): multiple definition of `Metadata::metadata'; C:\Users\adria\AppData\Local\Temp\ccdq4ZjN.o:main.cpp:(.bss+0x0): first defined here collect2.exe: error: ld returned 1 exit status

What's the error's cause?

Metadata.h: (Singleton class)

#pragma once
class Metadata
{
public:

    Metadata(Metadata &other) = delete;
    void operator=(const Metadata &other) = delete;

    static Metadata *getInstance()
    {
        return metadata;
    }

    static void createInstance(Ctor &params)
    {
        if (!metadata)
        {
            metadata = new Metadata(params);
        }
    }
protected:
    Metadata(Ctor &params)
    {
        m_vars = params;
    }

    static Metadata *metadata;

private:
    Ctor m_vars;
}

Metadata* Metadata::metadata = nullptr;

main.cpp:

#include "metadata.h"

int main(void)
{
    Ctor ctor;
    Metadata::createInstance(ctor);
    Metadata* data = Metadata::getInstance();
    return 0;
}

projectgen.cpp:

#include "metadata.h"

void ProjectGenerator::test()
{
    Metadata* data = Metadata::getInstance();
}

Upvotes: 2

Views: 827

Answers (2)

Michael Chourdakis
Michael Chourdakis

Reputation: 11158

The accepted answer is correct, I just want the option to declare the variable inline. This allows multiple definitions which are then taken as one.

inline Metadata* Metadata::metadata = nullptr;

Upvotes: 0

Sam Varshavchik
Sam Varshavchik

Reputation: 118340

An #include statement is logically equivalent to taking the included header file and physically inserting it into the .cpp file that's including it.

Metadata* Metadata::metadata = nullptr;

In the included header file, this defines this particular static class member. Therefore, every .cpp file that includes this header file defines this class member. You have two .cpp files that include this header file, and each one defines the same static class member.

This violates C++'s One Definition Rule. An object can be defined exactly once.

Simply move this definition to one of your .cpp files.

Upvotes: 1

Related Questions