考虑一个为初始化导出不同接口的库,在使用该库提供的任何其他内容之前,用户必须调用该接口。在该步骤中,查询某个系统状态并将其存储在相应的变量中。这不能映射到常量,但也不应该由于来自外部源的写入而容易发生变化,即系统状态应该在不同的翻译单元中可查询但不可写。
一个明显的例子是标记系统启动的时间戳。这不能是编译时常量,但也不应该是可写的。
这可以通过只实现静态函数并使用私有静态成员的类来实现:
// system.h
#include <chrono>
using sys_time_point = std::chrono::system_clock::time_point;
class System
{
public:
System () = delete;
// possibly other deleted functions
static bool init () noexcept;
static bool ready () noexcept;
static const sys_time_point& initTime() noexcept;
private:
static bool initState_;
static sys_time_point initTime_;
};
// system.cpp
bool System::initState_ = false;
sys_time_point System::initTime_ = std::chrono::system_clock::now();
问题是,我认为后一种方法是不恰当的设计选择,因为这些功能虽然可能相互依赖,但或多或少地定义了用于查询系统状态的杂项功能,而不是修改或访问用户定义类型的私有状态。
我宁愿选择第二种方法。假设一个namespace System
与前一个类具有相同功能的分组
// System.h
#include <chrono>
namespace System
{
using sys_time_point = std::chrono::system_clock::time_point;
bool init () noexcept; // needs to be called
bool ready () noexcept; // can be used by other lib components and lib clients
const sys_time_point& initTime() noexcept; // returns system startup time point
// other stuff here ...
}
// System.cpp
namespace System
{
namespace
{
bool sysInitState = false;
sys_time_point sysInitTime = std::chrono::system_clock::now();
}
bool init() noexcept
{
// init code here ... set and return sysInitState accordingly
}
bool ready() noexcept
{
return sysInitState;
}
const sys_time_point& initTime() noexcept
{
return sysInitTime;
}
}
使用未命名的命名空间,我禁止链接到其他翻译单元中的外部变量。AFAIK,除了使用namespace System
. 由于 const refs 或按值返回,也无法写入 - 除了邪恶的程序员可能const_cast<>
将 const refs 引用为 non-const refs 的情况。
我现在的问题是:
- 以上,第二个解决方案是否正确?
- 上述第二个解决方案可行吗?
- 还有其他可能更安全或更易于实施的解决方案吗?
感谢大家!