爱吃纳豆 2024-08-21 16:16 采纳率: 40%
浏览 31
已结题

c++ 单例模式 在不项目之间的引用问题

我在项目A里面

#pragma once
#ifndef TestSingleton_API_EXPORT  
#define TestSingleton_API_EXPORT _declspec(dllexport) 
#else 
#define TestSingleton_API_EXPORT _declspec(dllimport) 
#endif 
namespace test
{
    class TestSingleton_API_EXPORT TestSingleton
    {
    public:
        static TestSingleton* getTestSingleton(int);
        virtual void test() = 0;
    };
}

#include "TestSingleton.h"
#include<iostream>
#include"../test/Singleton.h"
#include"TestSingleton2.h"
using namespace std;

namespace test
{
    class TestSingletonPro :public TestSingleton
    {
        friend class Singleton<TestSingletonPro>;
    private:
        TestSingletonPro(int aaa)
            :m_pTestSingleton2(Singleton<TestSingleton2>::instance(aaa))
        {
            TestSingleton2* pTestSingleton2 = Singleton<TestSingleton2>::instance();

        }

        virtual void test()
        {
            cout << __FUNCTION__ << endl;
        }
    private:
        TestSingleton2* m_pTestSingleton2 = nullptr;

    };

    TestSingleton* TestSingleton::getTestSingleton(int aaaa)
    {
        return Singleton<TestSingletonPro>::instance(aaaa);
    }

}
#pragma once
#include<iostream>
#include"../test/Singleton.h"
using namespace std;

namespace test{
    class  TestSingleton2
    {
        friend class Singleton<TestSingleton2>;
    private:
        TestSingleton2(int aaqa) {
            cout << __FUNCTION__ << endl;
        }
    public:
 
        void test2()
        {
            cout << __FUNCTION__ << endl;
        }
    };
}

在项目B中

#pragma once
#include <utility>
#include <mutex> 
#include <type_traits>
// Trait to check if T can be default-constructed
template<typename T, typename = void>
struct CanDefaultConstruct : std::false_type {};

template<typename T>
struct CanDefaultConstruct<T, std::void_t<decltype(T())>> : std::true_type {};

template<typename T>
class Singleton
{
public:
    static T* instance()
    {
        if constexpr (CanDefaultConstruct<T>::value)
        {
            if (s_instance == nullptr)
            {
                std::lock_guard<std::mutex> lock(s_mutex);  // 确保线程安全
                if (s_instance == nullptr)  // 双重检查锁定
                {
                    s_instance = new T();  // 使用默认构造函数创建实例
                }
            }
        }
        return s_instance;
    }

    template<typename... Args>
    static T* instance(Args&&... args)
    {
        if (s_instance ==nullptr)
        {
            std::lock_guard<std::mutex> lock(s_mutex);  // Ensure thread-safety
            if (s_instance == nullptr)  // Double-checked locking
            {
                s_instance = new T(std::forward<Args>(args)...);
            }
        }
        return s_instance;
    }
    static void destroyInstance()
    {
        if (s_instance != nullptr)
        {
            delete s_instance;
            s_instance = nullptr;
        }
    }
private:
    Singleton(){}
    Singleton(const Singleton<T>&) {}
    ~Singleton() {
        if (s_instance != nullptr)
        {
            delete s_instance;
        }
    }
    Singleton<T>& operator = (const Singleton<T>)
    {}
private:
    static T* s_instance;
    static std::mutex s_mutex;
};

template<typename T>
T*Singleton<T>::s_instance = nullptr;
template<typename T>
std::mutex Singleton<T>::s_mutex;
#include <iostream>
#include"../Test1/TestSingleton.h"
#include"../Test1/TestSingleton2.h"
#include"Singleton.h"
using namespace test;
int main() {
 
    TestSingleton* pTestSingleton = TestSingleton::getTestSingleton(123234444);
    TestSingleton2* pTestSingleton2 = Singleton<TestSingleton2>::instance();
    pTestSingleton2->test2();
    return 0;
}

我的问题是 在项目B的main中 TestSingleton2* pTestSingleton2 = Singleton::instance();这句话以后 取不出A项目的代码里已经初始化的单例 这里一直返回nullptr

  • 写回答

22条回答 默认 最新

  • 杨同学* 2024-08-21 16:48
    关注
    获得0.90元问题酬金

    该回答引用ChatGPT4o及杨同学*共同作答, 如有帮助,还请采纳。
    你的问题是由于项目A和项目B之间的Singleton类模板实例化不一致导致的。在C++中,静态变量(如你的Singleton类中的静态成员变量 s_instance)在不同的编译单元(即不同的项目或库)中是独立的。因此,即使项目A已经创建并初始化了Singleton<TestSingleton2>的实例,项目B中的Singleton<TestSingleton2>仍然是一个全新的、未初始化的实例。

    为了在多个项目或模块之间共享单例实例,有几种方法可以解决这个问题:

    ### 1. **使用单独的静态库或动态库来定义Singleton模板:**
       - 将你的`Singleton`类模板放在一个单独的静态库或动态库中,这样所有项目都可以链接到同一个库,从而共享相同的Singleton实例。
    
    ### 2. **显式实例化:**
       - 在一个共享的头文件或源文件中显式地实例化Singleton模板,并在项目A和项目B中都包含相同的实例化。
    
    
       template class Singleton<TestSingleton2>; // 显式实例化Singleton<TestSingleton2>
    
    
       这将确保所有使用`Singleton<TestSingleton2>`的代码都引用同一个静态实例。
    
    ### 3. **使用外部定义的单例实例:**
       - 你可以将`Singleton<TestSingleton2>`的实例在项目A中初始化,然后在项目B中将这个实例通过某种方式传递给它。
       - 一种常见的做法是通过函数返回已创建的单例实例,例如:
    
       
       // 在项目A中
       TestSingleton2* getTestSingleton2Instance() {
           return Singleton<TestSingleton2>::instance();
       }
    
    
       然后在项目B中使用:
    
    
       // 在项目B中
       TestSingleton2* pTestSingleton2 = getTestSingleton2Instance();
    
    
    ### 4. **使用动态库导出实例:**
       - 如果你在项目A中构建了一个动态链接库(DLL),你可以导出`Singleton<TestSingleton2>`的实例,并在项目B中导入它:
    
       
       // 在项目A中(DLL中导出)
       extern template class Singleton<TestSingleton2>;
    
    
       在项目B中:
    
    
       // 在项目B中(DLL中导入)
       extern template class Singleton<TestSingleton2>;
    
    
    

    5. 利用全局变量:

    • 定义一个全局变量或静态变量来保存TestSingleton2的实例,并通过一个全局访问函数来获取这个实例。这样,不管是项目A还是项目B,都可以访问同一个实例。

    总结

    如果项目A和项目B是独立编译的,在这种情况下共享静态数据(如Singleton的静态成员)是不可能的。解决方法通常是在共享库中定义Singleton模板,或通过其他机制共享初始化的实例。

    在你的代码结构中,我建议你将Singleton模板类放到一个单独的静态库或动态库中,然后让项目A和项目B都链接这个库,这样可以确保所有模块都能访问同一个Singleton<TestSingleton2>实例。

    评论

报告相同问题?

问题事件

  • 系统已结题 8月29日
  • 创建了问题 8月21日

悬赏问题

  • ¥15 fluent设置了自动保存后,会有几个时间点不保存
  • ¥20 激光照射到四象线探测器,通过液晶屏显示X、Y值
  • ¥15 这怎么做,怎么在我的思路下改下我这写的不对
  • ¥50 数据库开发问题求解答
  • ¥15 安装anaconda时报错
  • ¥20 如何用Python处理单元格内连续出现的重复词语?
  • ¥15 小程序有个导出到插件方式,我是在分包下引入的插件,这个export的路径对吗,我看官方文档上写的是相对路径
  • ¥20 希望有人能帮我完成这个设计( *ˊᵕˋ)
  • ¥100 将Intptr传入SetHdevmode()将Intptr传入后转换为DEVMODE的值与外部代码不一致
  • ¥50 基于ERA5数据计算VPD