Home > Software design >  How to implement Singleton C the right way
How to implement Singleton C the right way

Time:07-18

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();
}

CodePudding user response:

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.

CodePudding user response:

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;

  •  Tags:  
  • c
  • Related