Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在单例中传递参数_C++_Singleton_Argument Passing - Fatal编程技术网

C++ 如何在单例中传递参数

C++ 如何在单例中传递参数,c++,singleton,argument-passing,C++,Singleton,Argument Passing,我一直在想如何将参数传递给单例构造函数。我已经知道怎么做单身汉了,但我很不幸找到了一个方法 这是我的代码(它的一部分) Questionnary*Questionnary::getInstance(){ 静态问号*问号=空; 如果(问题==NULL){ 是否可以有一个方法来创建实例以将参数传递给构造函数,如果在调用CreateInstance之前没有调用它,则可以在getInstance()方法中进行断言。例如: class Questionnary { private: // cons

我一直在想如何将参数传递给单例构造函数。我已经知道怎么做单身汉了,但我很不幸找到了一个方法

这是我的代码(它的一部分)

Questionnary*Questionnary::getInstance(){
静态问号*问号=空;
如果(问题==NULL){

是否可以有一个方法来创建实例以将参数传递给构造函数,如果在调用CreateInstance之前没有调用它,则可以在getInstance()方法中进行断言。例如:

class Questionnary
{
private:
    // constructor taking string:
    Questionnary(const std::string& name) : name_(name) 
    {
        std::cout << "My name is: " << q.name_ << std::endl; 
    }

    static Questionnary* m_instance;
public:
    static void createInstance(const std::string& name)
    {
        assert(!m_instance);
        m_instance = new Questionary(name);
    }

    static void destroyInstance()
    {
        assert(m_instance);
        delete m_instance;
    }

    static Questionnary* Questionnary::getInstance()
    {
        assert(m_instance);
        return m_instance;
    }
private:
    std::string name_;
};
课堂提问
{
私人:
//构造函数获取字符串:
问题(const std::string&name):名称(name)
{

std::cout您不需要动态分配singleton的实例。它可以如下所示(这有时称为“延迟加载singleton”~实例创建较晚&有点“自动”):

请注意,当第一次调用
getInstance
时,构造函数只会被正确调用一次。

让我扩展一下您的用例。我建议在这种特殊情况下使用参数指针,因为我们利用了它的固有属性,它可以是“空的”

我发现这种方法不那么令人困惑,因为它让您在第一次初始化后获得实例,而不需要(无论如何都要丢弃)参数:

// first init
Questionnary::init("my single Questionnary");

// later on ...
Questionnary& q = Questionnary::getInstance();

<> > >编辑< <强>:从GETSimple函数中删除参数,并进行一些优化。

< P>使用现代C++的我的版本,包括了现有的类型:

#ifndef SINGLETON_H
#define SINGLETON_H

template <typename C, typename ...Args>
class singleton
{
private:
  singleton() = default;
  static C* m_instance;

public:
  ~singleton()
  {
    delete m_instance;
    m_instance = nullptr;
  }
  static C& instance(Args...args)
  {
    if (m_instance == nullptr)
      m_instance = new C(args...);
    return *m_instance;
  }
};

template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;

#endif // SINGLETON_H
\ifndef SINGLETON\u H
#定义单例
模板
单件阶级
{
私人:
singleton()=默认值;
静态C*m_实例;
公众:
~singleton()
{
删除m_实例;
m_实例=nullptr;
}
静态C&实例(Args…Args)
{
if(m_实例==nullptr)
m_实例=新的C(参数…);
返回*m_实例;
}
};
模板
C*singleton::m_instance=nullptr;
#endif//SINGLETON_H
以下是在单元测试中的外观:

  int &i = singleton<int, int>::instance(1);
  UTEST_CHECK(i == 1);

  tester1& t1 = singleton<tester1, int>::instance(1);
  UTEST_CHECK(t1.result() == 1);

  tester2& t2 = singleton<tester2, int, int>::instance(1, 2);
  UTEST_CHECK(t2.result() == 3);
int&i=singleton::instance(1);
UTEST_检查(i==1);
tester1&t1=singleton::instance(1);
UTEST_检查(t1.result()=1);
tester2&t2=singleton::instance(1,2);
UTEST_检查(t2.result()=3);
问题是instance()在每次调用时都需要参数,但只在第一次调用时使用参数(如上所述)。通常不能使用默认参数。最好在调用instance()之前使用create(Args…)方法,或者引发异常。

/!@file singleton.h
//! @file singleton.h
//!
//! @brief Variadic template to make a singleton out of an ordinary type.
//!
//! This template makes a singleton out of a type without a default
//! constructor.

#ifndef SINGLETON_H
#define SINGLETON_H

#include <stdexcept>

template <typename C, typename ...Args>
class singleton
{
private:
  singleton() = default;
  static C* m_instance;

public:
  singleton(const singleton&) = delete;
  singleton& operator=(const singleton&) = delete;
  singleton(singleton&&) = delete;
  singleton& operator=(singleton&&) = delete;

  ~singleton()
  {
    delete m_instance;
    m_instance = nullptr;
  }

  static C& create(Args...args)
  {
    if (m_instance != nullptr)
      {
    delete m_instance;
    m_instance = nullptr;
      }
    m_instance = new C(args...);
    return *m_instance;
  }

  static C& instance()
  {
    if (m_instance == nullptr)
      throw std::logic_error(
        "singleton<>::create(...) must precede singleton<>::instance()");
    return *m_instance;
  }
};

template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;

#endif // SINGLETON_H
//! //!@简短的变量模板,使普通类型成为单例。 //! //!此模板从没有默认值的类型中生成单例 //!构造函数。 #ifndef SINGLETON_H #定义单例 #包括 模板 单件阶级 { 私人: singleton()=默认值; 静态C*m_实例; 公众: 单例(const singleton&)=删除; 单例&运算符=(常量单例&)=delete; 单例(单例&&)=删除; 单例&运算符=(单例&&)=删除; ~singleton() { 删除m_实例; m_实例=nullptr; } 静态C&create(Args…Args) { if(m_实例!=nullptr) { 删除m_实例; m_实例=nullptr; } m_实例=新的C(参数…); 返回*m_实例; } 静态C&实例() { if(m_实例==nullptr) 抛出std::逻辑错误( “singleton::create(…)必须位于singleton::instance()之前”; 返回*m_实例; } }; 模板 C*singleton::m_instance=nullptr; #endif//SINGLETON_H
以及:

void
单例测试::测试()
{
尝试
{
singleton::instance();
UTEST_检查(错误);
}
捕获(标准::逻辑错误&e)
{
检查是否正确;
}
尝试
{
UTEST_检查((单例::创建(1)==1));
UTEST_检查((singleton::instance()==1));
}
捕获(…)
{
UTEST_检查(错误);
}
使用stester0=单态;
尝试
{
stester0::instance();
UTEST_检查(错误);
}
捕获(标准::逻辑错误&e)
{
检查是否正确;
}
尝试
{
UTEST_检查((stester0::create().result()=0));
UTEST_检查((stester0::instance().result()=0));
}
捕获(…)
{
UTEST_检查(错误);
}
使用stester1=单态;
尝试
{
stester1::instance();
UTEST_检查(错误);
}
捕获(标准::逻辑错误&e)
{
检查是否正确;
}
尝试
{
UTEST_检查((stester1::create(1.result()==1));
UTEST_检查((stester1::instance().result()==1));
}
捕获(…)
{
UTEST_检查(错误);
}
使用stester2=单态;
尝试
{
stester2::instance();
UTEST_检查(错误);
}
捕获(标准::逻辑错误&e)
{
检查是否正确;
}
尝试
{
UTEST_CHECK((stester2::create(1,2.result()==3));
UTEST_检查((stester2::instance().result()=3));
}
捕获(…)
{
UTEST_检查(错误);
}
}

不动态分配单例是正确的想法,但是如果您打算直接分配数据成员,那么使用构造函数参数有什么意义呢?@Praetorian:这是为了指出,传递的字符串也可以用于在下一次
getInstance
调用中更改该单例的状态,但是你是对的,这使得构造函数在这里毫无用处。谢谢,如果我做对了,那么我只需要将参数放入getInstance函数中,然后将其传递给构造函数。我如何向这个实现中添加一个没有参数的getInstance方法?(以后只需获取实例,不需要传递参数)我不明白为什么这是公认的答案,因为它演示了如何不能将参数传递给singleton的构造函数。此外,要求传递参数,即使它将被igonored用于除第一个调用以外的所有调用,也是一个主要的混淆源,因为您已经有了singleton,所以
#ifndef SINGLETON_H
#define SINGLETON_H

template <typename C, typename ...Args>
class singleton
{
private:
  singleton() = default;
  static C* m_instance;

public:
  ~singleton()
  {
    delete m_instance;
    m_instance = nullptr;
  }
  static C& instance(Args...args)
  {
    if (m_instance == nullptr)
      m_instance = new C(args...);
    return *m_instance;
  }
};

template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;

#endif // SINGLETON_H
  int &i = singleton<int, int>::instance(1);
  UTEST_CHECK(i == 1);

  tester1& t1 = singleton<tester1, int>::instance(1);
  UTEST_CHECK(t1.result() == 1);

  tester2& t2 = singleton<tester2, int, int>::instance(1, 2);
  UTEST_CHECK(t2.result() == 3);
//! @file singleton.h
//!
//! @brief Variadic template to make a singleton out of an ordinary type.
//!
//! This template makes a singleton out of a type without a default
//! constructor.

#ifndef SINGLETON_H
#define SINGLETON_H

#include <stdexcept>

template <typename C, typename ...Args>
class singleton
{
private:
  singleton() = default;
  static C* m_instance;

public:
  singleton(const singleton&) = delete;
  singleton& operator=(const singleton&) = delete;
  singleton(singleton&&) = delete;
  singleton& operator=(singleton&&) = delete;

  ~singleton()
  {
    delete m_instance;
    m_instance = nullptr;
  }

  static C& create(Args...args)
  {
    if (m_instance != nullptr)
      {
    delete m_instance;
    m_instance = nullptr;
      }
    m_instance = new C(args...);
    return *m_instance;
  }

  static C& instance()
  {
    if (m_instance == nullptr)
      throw std::logic_error(
        "singleton<>::create(...) must precede singleton<>::instance()");
    return *m_instance;
  }
};

template <typename C, typename ...Args>
C* singleton<C, Args...>::m_instance = nullptr;

#endif // SINGLETON_H
void
singleton_utest::test()
{
  try
    {
      singleton<int, int>::instance();
      UTEST_CHECK(false);
    }
  catch (std::logic_error& e)
    {
      UTEST_CHECK(true);
    }

  try
    {
      UTEST_CHECK((singleton<int, int>::create(1) == 1));
      UTEST_CHECK((singleton<int, int>::instance() == 1));
    }
  catch (...)
    {
      UTEST_CHECK(false);      
    }

  using stester0 = singleton<tester0>;

  try
    {
      stester0::instance();
      UTEST_CHECK(false);
    }
  catch (std::logic_error& e)
    {
      UTEST_CHECK(true);
    }

  try
    {
      UTEST_CHECK((stester0::create().result() == 0));
      UTEST_CHECK((stester0::instance().result() == 0));
    }
  catch (...)
    {
      UTEST_CHECK(false);      
    }

  using stester1 = singleton<tester1, int>;

  try
    {
      stester1::instance();
      UTEST_CHECK(false);
    }
  catch (std::logic_error& e)
    {
      UTEST_CHECK(true);
    }

  try
    {
      UTEST_CHECK((stester1::create(1).result() == 1));
      UTEST_CHECK((stester1::instance().result() == 1));
    }
  catch (...)
    {
      UTEST_CHECK(false);      
    }

  using stester2 = singleton<tester2, int, int>;

  try
    {
      stester2::instance();
      UTEST_CHECK(false);
    }
  catch (std::logic_error& e)
    {
      UTEST_CHECK(true);
    }

  try
    {
      UTEST_CHECK((stester2::create(1, 2).result() == 3));
      UTEST_CHECK((stester2::instance().result() == 3));
    }
  catch (...)
    {
      UTEST_CHECK(false);      
    }
}