在函数的命名空间中初始化变量

问题描述

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

.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 没有默认构造函数(而且我不希望它有一个)。但是当我删除 2nd 中的 .cpp 行时,出现链接器错误 unresolved external symbol

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

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

解决方法

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

然后你就不能在不将值传递给它的构造函数的情况下创建一个 Variable 的实例,例如:

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

Variable MyNS::var(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,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,c); }

另一种解决方案是将 var 改为 std::optional<Variable>,例如:

#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,c); }

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

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

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...