【问题标题】:Initialize a variable in a namespace in a function在函数的命名空间中初始化变量
【发布时间】:2021-04-06 22:06:14
【问题描述】:

我已经多次在命名空间中设置变量时遇到了麻烦,但现在通常通过如下设置来解决它:

.h

namespace MyNS {
    extern Variable var;
}

.cpp

#include "MyNS.h"
Variable MyNS::var;

现在,这适用于原语,但当 Variable 对象有点复杂时就会出现问题。

也就是说,我这次的问题是我想在调用某个函数之前让一些变量保持未初始化状态。如下:

.h

namespace MyNS {
    extern Variable var;
    void init();
}

.cpp

#include "MyNS.h"
Variable MyNS::var;
void MyNS::init() { var = Variable(a, b, c); }

这会产生编译时错误,因为Variable 没有默认构造函数(而且我不希望它有默认构造函数)。但是当我删除.cpp 中的2nd 行时,我得到链接器错误unresolved external symbol

我该如何解决这个问题?如何“稍后”初始化命名空间的变量?

到目前为止,我的“hacky”解决方案是让我的命名空间保存一个Variable*,将其初始化为nullptr,然后在我的init 函数中为其分配实际对象。但对于如此简单的事情来说,这似乎令人难以置信,因为在这种情况下我没有真正的理由使用指针。

【问题讨论】:

  • "Variable 没有默认构造函数(而且我不希望它有一个)" - 那么你不能在不传递的情况下创建它的实例值到它的构造函数中,例如:Variable MyNS::var(0,0,0);。否则,您将不得不将var 改为Variant* 指针,然后init() 可以new 它。
  • @RemyLebeau 这就是我目前所拥有的,但这太老套了!命名空间到底有什么特别之处,以至于不可能实现这么简单的事情?或者我对 C++ 的一般理解是如此错误以至于我试图尝试这样做?
  • 这与命名空间完全无关。这就是对象构造的一般工作方式。如果一个类没有默认构造函数,那么如果不向其构造函数提供所需的值或使用Aggregate Initialzation,您就无法创建它的实例。
  • Fly,您可以将延迟加载的 static 变量隐藏在另一个类似于 Meyer's Singleton 的包装器内的函数中,但这也好不了多少。
  • 那么(智能)指针可能是最好的解决方案。

标签: c++ namespaces initialization extern


【解决方案1】:

变量没有默认构造函数(我也不希望它有)

如果不将值传递给其构造函数,您就无法创建Variable 的实例,例如:

namespace MyNS {
    extern Variable var;
    void init();
}
#include "MyNS.h"

Variable MyNS::var(0, 0, 0);

void MyNS::init() { var = Variable(a, b, c); }

另一种解决方案是将var改为Variable*指针,然后init()可以new它,例如:

namespace MyNS {
    extern Variable* var;
    void init();
    void cleanup();
}
#include "MyNS.h"

Variable* MyNS::var = nullptr;

void MyNS::init() { var = new Variable(a, b, c); }
void MyNS::cleanup() { delete var; }

或者:

#include <memory>

namespace MyNS {
    extern std::unique_ptr<Variable> var;
    void init();
}
#include "MyNS.h"

std::unique_ptr<Variable> MyNS::var;

void MyNS::init() { var = std::make_unique<Variable>(a, b, c); }

另一种解决方案是将var 改为std::optional&lt;Variable&gt;,例如:

#include <optional>

namespace MyNS {
    extern std::optional<Variable> var;
    void init();
}
#include "MyNS.h"

std::optional<Variable> MyNS::var;

void MyNS::init() { var = Variable(a, b, c); }

另一种解决方案是将var 包裹在单例中,例如:

namespace MyNS {
    struct VariableAccess {
        static Variable& Var();
    };
}
#include "MyNS.h"

Variable& MyNS::VariableAccess::Var() {
    static Variable var(a, b, c);
    return var;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多