【发布时间】:2020-01-31 11:11:48
【问题描述】:
假设我有一个类Super,其中我有一个Super 类型的静态成员,它只定义了一个常用的Super 实例
// super.hpp
class Super
{
public:
Super(const double a):
m_a(a)
{}
double a() const { return m_a; }
static const Super thing; // use this a lot in code
private:
double m_a;
};
实施
// super.cpp
#include "super.hpp"
const Super Super::thing = Super(1.0); // definition
在这一点上我认为一切都很好,但如果不是,请纠正我。
现在我也有Super 的子类,具有类似的静态成员
// sub.hpp
#include "super.hpp"
class Sub : public Super
{
public:
Sub(const double a):
Super(a)
{}
explicit Sub(const Super& obj):
Super(obj)
{}
static const Sub thing;
};
实施
// sub.hpp
#include "sub.hpp"
const Sub Sub::thing = Sub(Super::thing); // WORKS IN MYSTERIOUS WAYS
最后是一个示例用法
// main.cpp
#include <iostream>
#include "sub.hpp"
int main()
{
Super super = Super::thing;
std::cout << super.a() << std::endl;
Sub sub = Sub::thing;
std::cout << sub.a() << std::endl;
}
当我使用以下设置编译它时
// CMakeLists.txt
project (hello)
add_executable(hello main.cpp super.cpp sup.cpp)
我得到了预期的输出
$ ./hello
1
1
但是如果我在CMakeLists 中更改cpp 文件的顺序(sub.cpp 在super.cpp 之前)
// CMakeLists.txt
project (hello)
add_executable(hello main.cpp sup.cpp super.cpp)
我明白了
$ ./hello
1
0
我认为这是static initialization order ‘fiasco’(?)的一个例子,我对它发生的原因有所了解。
所以问题变成了:有什么方法可以得到关于未初始化静态的警告,或者有什么方法可以避免这个问题?
我已经阅读了How do I prevent the “static initialization order problem”?,但我希望能够保留Sub::thing 接口,并避免将其替换为Sub::thing()。
【问题讨论】:
-
我的构造函数非常简单(它们的主体是空的,我只是分配初始化列表中的所有值),所以我可能可以这样做,但我需要更多关于如何做到这一点的指导。我对
constexpr不是很熟悉。 -
我尝试将
thing设为inline static而不是static,但由于Super的类型不完整,因此出现错误。 -
是的,我认为问题在于,编译器没有看到类的完整定义。这很奇怪,因为那时它不需要它。如果
thing不是班级的成员,而只是班级之外的全球成员,它应该可以工作。我删除了我的建议。我稍后会尝试正确执行此操作。 -
我找到了一个可能有用的类似问题的答案:stackoverflow.com/a/32134757/1850917
-
好吧,我的意思是this,但同样,这取决于您的用例。
标签: c++