Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

c++ - Template singleton base class in shared object

I'm currently porting my project from Windows to Linux.

The project consists of a 'main' shared library, several plugins (also shared libraries) and a launcher application.

Within the 'main' shared library there's a template singleton class another class can inherit from to use the singleton pattern.

The template singleton class is implemented as follows:

    template<class T>
    class Singleton
    {
    public:
        static T* getInstance()
        {
          if(!m_Instance)
          {
            m_Instance = new T();
          }

          return m_Instance; 
        }
    private:
        static T* m_Instance;

    protected:
        Singleton()
        {
          assert(!m_Instance);
          m_Instance = (T*)this;
        }

        ~Singleton()
        {
          m_Instance = 0;
        }
    };

template<class T> T* Singleton<T>::m_Instance = 0;

A class that inherits from the Singleton class is - for example - the Logger class. So whenever I call

Logger::getInstance()

I get a valid instance of the logger class.

For windows this works across multiple DLLs.

If I instantiate the logger in the 'main' dll and try to get the instance in plugin A and B, it'll always return the same instance.

On Linux however I can not reproduce this behavior. For both plugin A and B the assert

assert(!m_Instance);

triggers and the program stops.

What do I have to do to get the same behavior as I have in Windows with dlls?

I tried linking with -rdynamic but unfortunately this didn't solve the problem.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

IMHO the closest thing you can get that suffices your requirements is something using the following pattern:

#include <iostream>

template<class Derived>
class Singleton {
public:
    static Derived& instance() {
        static Derived theInstance;
        return theInstance;
    }

protected:
    Singleton() {}

private:
    Singleton(const Singleton<Derived>&);
    Singleton<Derived>& operator=(const Singleton<Derived>&);
};

class ASingleton : public Singleton<ASingleton> {
public:
    void foo() { std::cout << "foo() called ..." << std::endl; }
};

int main() {
    ASingleton& a = ASingleton::instance();
    a.foo();
    return 0;
}

Whatever you want to be accessible through an interface might be injected using multiple inheritance. Though the benefit of using a Singleton<Derived> base class is a bit questionable, it just provides that narrow instance() implementation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...