我正在将一个类移植到C ++,并且需要在创建我的类的第一个实例之前执行一些初始化代码;在main()
获得控制权之前执行代码适合我。如何在C ++中实现?
答案 0 :(得分:10)
您可以在namespace
范围内使用对象的构造函数。
namespace {
struct Init
{
Init()
{
// Initialization code here.
}
} init_;
} // namespace
请注意,这有一些限制,特别是在Windows上。在Windows上,在保持加载程序锁的情况下调用ctor,因此您无法执行任何需要加载DLL等的操作。这包括WinSock的初始化,因为它可以尝试加载外部DLL。
根据某些消息来源,您可以使用QueueUserAPC
解决此限制。这种技术也有局限性,尽管不同。我已经使用了这个,我的实验表明,只有当你使用Visual Studio及其C库作为 DLL ,即MSVCRT.DLL,MSVCR100.DLL等时,这才有效。({{1} }或/MD
开关)
这是一个link to similar issue(我的,实际上)有一个重要的位:
经过一些测试后,如果我从DllMain()排队APC,APC方法似乎有效,但如果我从一个类的静态全局实例的ctor排队APC,它就不起作用。
答案 1 :(得分:2)
在main()开始执行之前构造全局和静态类。
class hello {
hello () { std::cout << "hello" << std::endl; }
};
hello hi;
int main(){
std::cout << "hello again" << std::endl;
return 0;
}
输出将始终为
hello
hello again
因为hello对象实例是在main启动之前创建的,因为hi是类hello的全局实例
答案 2 :(得分:2)
我的回答解决了你的真正问题 - 在你的班级的第一个实例之前执行一次初始化,而不是在main之前执行。
只需使用静态变量即可确保只执行一次init代码。如果您需要是线程安全的,请使用同步,尽管它会有性能损失。
class MyClass {
MyClass() {
// Perform the one-time initialization.
static bool passed = false;
if (!passed) {
performOneTimeInitialization();
passed = true;
}
// Continue with normal construction.
}
};
答案 3 :(得分:1)
struct Init
{
Init()
{
/* Your Initialization Code */
}
} x;
int main()
{
}
答案 4 :(得分:1)
您真正问题的另一种解决方案(使用工厂方法):
namespace
{
struct Initializer
{
Initializer()
{
/* initializing code goes here */
}
}
}
MyClass CreateMyClass()
{
static Initializer init;
return new MyClass();
}
初次化代码在您第一次调用CreateMyClass时执行。它应该是使用C ++ 11编译器的线程安全。如果你没有并且需要线程安全,你可以检查boost :: call_once。
答案 5 :(得分:0)
你实际上在这里提出两个不同的问题,一个描述你想要解决的问题:
我需要在创建第一个类的实例之前执行一些初始化代码;
第二个问题是关于你如何看待问题的解决方法:
在main()获得控制权之前执行代码适合我。如何在C ++中实现?
对于第二个问题,您已多次获得一个答案(全局变量)。这可能是一个可行的解决方案,虽然我更喜欢私有静态类成员来限制该全局变量的可见性:
class X {
const static bool initialized;
};
//X.cpp:
namespace {
bool preInitialization() {
//your pre-main code here
return true;
}
}
bool X::initialized = preInitialization();
对于第一个问题,你可以延迟执行初始化代码,直到你的类的第一个变量被初始化为止:
class X {
X();
};
//X.cpp:
namespace {
bool preInitialization() {
//your pre-main code here
return true;
}
}
X::X() {
static bool b = preInitialization();
}
这样你的代码在的第一个构造函数调用期间执行。这可能有一些缺点,例如:如果X的成员只能在执行初始化代码之后初始化,或者存在多个构造函数。您可以通过将其推入空基类来优化该方法:
class PreInit {
static bool preInitialization() {
//your pre-main code here
return true;
}
public:
PreInit() {
static bool b =preInitialization();
}
};
class X : private PreInit {
//normal class implementation
};
这样你甚至可以在第一次构造多个类的任何对象之前执行代码,只需从PreInit类派生所有有问题的类。只有更好的设计才能将预初始化分解为自己的类,遵守SRP。