2

我正在将一个类移植到 C++,并且需要在创建我的类的第一个实例之前执行一些初始化代码;在获得控制权之前执行代码main()适合我。如何在 C++ 中做到这一点?

4

6 回答 6

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 等(/MD/MDd开关)

更新 2

这是一个指向类似问题(实际上是我的)的链接,其中包含一个重要问题:

经过一些测试后,如果我从 DllMain() 将 APC 排队,似乎 APC 方法有效,但如果我从类的静态全局实例的 ctor 排队 APC,则它不起作用。

于 2013-08-12T09:00:21.467 回答
2

My answer addresses your real problem - performing one-time initialization before the first instance of your class, not executing before main.

Just use a static variable to make sure you execute the one time init code only once. Use synchronization if you need to be thread-safe, though it would have a performance hit.

class MyClass {
    MyClass() {
         // Perform the one-time initialization.
         static bool passed = false;
         if (!passed) {
             performOneTimeInitialization();
             passed = true;
         }

         // Continue with normal construction.
    }
};
于 2013-08-12T09:14:13.513 回答
2
struct Init
{
   Init() 
   {
      /* Your Initialization Code */
   }
} x;

int main()
{

}
于 2013-08-12T08:59:24.900 回答
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 的全局实例

于 2013-08-12T09:00:30.533 回答
1

您实际问题的另一个解决方案(使用工厂方法):

namespace 
{
    struct Initializer
    {
        Initializer()
        {
        /* initializing code goes here */
        }
    }
}

MyClass CreateMyClass()
{
    static Initializer init;
    return new MyClass();
}

第一次调用 CreateMyClass 时会执行初始化代码。对于 C++11 编译器,它甚至应该是线程安全的。如果你没有并且需要线程安全,你可以检查 boost::call_once。

于 2013-08-12T09:26:09.517 回答
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 的第一次构造函数调用期间执行。这可能有一些缺点,例如,如果 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,这只是一个更好的设计。

于 2013-08-12T09:59:19.473 回答