【问题标题】:Constructing a static member variable late后期构造静态成员变量
【发布时间】:2015-11-30 16:29:28
【问题描述】:

我有一个需要使用非默认构造函数构造的类的静态成员。代码是这样的:

class MyClass
{
public:
   static void initialise(int arg1, int arg2)
   {
      static MyClass instance(arg1, arg2);
      _instance = instance;
   }

   static MyClass& instance()
   {
      return _instance;
   }

   /* Other non-static functions used with the return of instance()... */

private:
   MyClass(int arg1, int arg2)
      : _arg1(arg1), _arg2(arg2) {}

   static MyClass& _instance;
   int _arg1, _arg2;
};

我这样做是因为在应用程序的生命周期内我需要一个类的实例,但是它需要使用只有在读取配置后才知道的参数来构造。 MyClass 的超类将调用 MyClass 中的覆盖,这取决于了解这些配置项。

我一直在尝试找到一种方法来声明一个静态 MyClass 成员,该成员最初只是一个占位符,以便以后可以构造它,但我的测试表明这似乎是不可能的。测试如下:

#include <cstdio>

class CNoDefCtor
{
public:
    CNoDefCtor(int arg1)
        : _arg1(arg1)
    {
        printf("%s\n", __func__);
    }

    virtual ~CNoDefCtor()
    {
        printf("%s\n", __func__);
    }

    static void Initialise(int arg1)
    {
        printf("%s\n", __func__);
        CNoDefCtor _instance(arg1); /* Actually construct here?!? */
    }

    static CNoDefCtor& instance()
    {
        return _instance;
    }

    int Arg1()
    {
        return _arg1;
    }

private:
    int _arg1;
    static CNoDefCtor _instance;
};

int main()
{
    printf("%s\n", __func__);

    CNoDefCtor ndc; /* Placeholder? */
    ndc.Initialise(1);
    printf("%d\n", ndc.Instance().Arg1());

    printf("%s\n", __func__);
}

所以我想我的问题是:你如何声明但不构造静态成员?我认为如果它没有默认构造函数是可能的。

请告诉我我遗漏了一些简单的东西,并且有一种简单的方法可以做到这一点。

【问题讨论】:

  • 为什么不将静态成员保留为指针(或 shared_ptr)?默认值为 NULL,create() 将调用 new...
  • 既然你有一个 instance() 函数,将实际对象设为 instance() 函数的静态变量会简单得多,而不是类的静态成员。
  • 根据您要求的其他详细信息,我希望您希望唯一的构造函数是一个不执行任何操作的私有默认构造函数,然后使用非构造函数处理初始化。

标签: c++ static static-members


【解决方案1】:

你在这里尝试做的是一个经典的单例类。 https://en.wikipedia.org/wiki/Singleton_pattern

您在第一个代码块中编写的类定义很好,应该可以工作。类静态对象将在第一次调用 initialise() 时被初始化。

我认为问题出在您的测试代码上,您不应该需要 main 中的占位符变量。这将创建您的单例类的对象,您显然不想要它。

因此,简而言之,要纠正您的单例类,无论何时编写单例类,您都必须遵守以下规则,

  1. 私有的默认构造函数。
  2. 初始化函数是静态的。
  3. 类定义中的静态变量(实例)应该是指针或引用变量。

所以你的新测试类定义应该是这样的,

class CNoDefCtor : public CAnnoyingClass
{
private:
    CNoDefCtor(int arg1)
        : _arg1(arg1)
    {
        printf("%s\n", __func__);
    }

public:
    virtual ~CNoDefCtor()
    {
        printf("%s\n", __func__);
    }

    static void Initialise(int arg1)
    {
        printf("%s\n", __func__);
        _instance = new CNoDefCtor(arg1);
    }

    static CNoDefCtor& instance()
    {
        return *_instance;
    }

    int Arg1()
    {
        return _arg1;
    }

private:
    int _arg1;
    static CNoDefCtor *_instance;
};

int main()
{
    printf("%s\n", __func__);

    CNoDefCtor::Initialise(1);
    printf("%d\n", CNoDefCtor::Instance().Arg1());

    printf("%s\n", __func__);
}

【讨论】:

    猜你喜欢
    • 2020-07-15
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多