如何在main()获得控制权之前编写要执行的代码?

时间:2013-08-12 08:54:35

标签: c++

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

6 个答案:

答案 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开关)

更新2

这是一个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。