问题描述
我已经多次在命名空间中设置变量时遇到问题,但现在通常通过如下设置来解决它:
.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;
};