什么是静态构造函数?

时间:2011-04-27 12:18:07

标签: c++

在接受采访时我问过这个问题:

  

什么是静态构造函数?

它是否存在于C ++中?如果是,请以示例解释。

13 个答案:

答案 0 :(得分:67)

C ++没有静态构造函数,但您可以使用嵌套类的静态实例来模拟它们。

class has_static_constructor {
    friend class constructor;

    struct constructor {
        constructor() { /* do some constructing here … */ }
    };

    static constructor cons;
};

// C++ needs to define static members externally.
has_static_constructor::constructor has_static_constructor::cons;

答案 1 :(得分:16)

在C ++中,没有静态构造函数。在C#中(也可能在Java中),您可以定义静态构造函数,该构造函数由运行时自动调用,以便初始化静态成员。

如需进一步的问题和兴趣,请阅读以下主题:

What is the rationale for not having static constructor in C++?

答案 2 :(得分:9)

由于我们在技术上没有C ++中的静态构造函数,你必须决定是否值得做一些棘手的事情来强制解决问题(例如使用嵌套类的静态实例),或者只是稍微重构代码在程序生命的早期调用静态初始化程序。

#include <iostream>           // cout, endl

class Foo {
   public:
      static int s_count;

      // Constructor definition
      Foo (int l, int w, int h)
      {
         cout <<"Foo ctor called." << endl;
         length = l;
         width  = w;
         height = h;

         // Increase every time object is created
         s_count++;
      }

      int vol ()
      {
         return length * width * height;
      }

      static void initCount()
      {
         s_count = 0;
      }

      static int getCount()
      {
         return s_count;
      }

   private:
      double length;     // Length of a box
      double width;      // Width  of a box
      double height;     // Height of a box
};

// Initialize static member of class Foo
int Foo::s_count;  // Initializing here is non-deterministic

int main(void) {

   Foo::initCount();  // Initializing here is deterministic

   // Print total number of objects before creating object.
   cout << "Inital Count: " << Foo::getCount() << endl;

   Foo Foo1(3, 1, 1);    // Declare box1
   Foo Foo2(8, 6, 2);    // Declare box2

   // Print total number of objects after creating object.
   cout << "Final Count: " << Foo::getCount() << endl;

   return 0;
}

Output:

$ static_init_test
Inital Count: 0
Foo ctor called.
Foo ctor called.
Final Count: 2

我更喜欢这种方法;作为一线希望,它将非确定性初始化。

虽然有一个问题 - 如果你试图初始化静态const变量,这种技术是不够的。对于静态const变量,您必须将它们设置为类的私有,并为外人提供读取它们的getter。

注意:我更新了此代码 - 它通过以下方式编译并成功运行,没有任何警告:

g++ static_init_test.cpp -std=c++11 -o static_init_test

答案 3 :(得分:6)

静态构造函数存在于C#和Java中 它们用于初始化类的静态成员 运行时在首次使用类之前执行它们。

答案 4 :(得分:3)

C ++中没有这样的东西。构造函数和描述符通常用于创建或破坏对象的实例。没有相应的对象实例就调用它们是没有意义的。您可以使用singleton模式模拟它们。

答案 5 :(得分:2)

可能是这个意思:

class Cat
{
private:
Cat();
public:
static Cat getCat() {return Cat(); }
}

答案 6 :(得分:2)

静态构造函数用于初始化类的静态数据。 C ++没有静态构造函数。但是可以使用友元类或嵌套类来模拟静态构造函数,如下所示。

class ClassStatic{
private:
    static char *str;
public:
    char* get_str() { return str; }
    void set_str(char *s) { str = s; }
    // A nested class, which used as static constructor
    static class ClassInit{
    public:
        ClassInit(int size){ 
            // Static constructor definition
            str = new char[size];
            str = "How are you?";
        }
    } initializer;
};

// Static variable creation
char* ClassStatic::str; 
// Static constructor call
ClassStatic::ClassInit ClassStatic::initializer(20);

int main() {
    ClassStatic a;
    ClassStatic b;
    std::cout << "String in a: " << a.get_str() << std::endl;
    std::cout << "String in b: " << b.get_str() << std::endl;
    a.set_str("I am fine");
    std::cout << "String in a: " << a.get_str() << std::endl;
    std::cout << "String in b: " << b.get_str() << std::endl;
    std::cin.ignore();
}

输出:

String in a: How are you?
String in b: How are you?
String in a: I am fine
String in b: I am fine

答案 7 :(得分:0)

在C ++中,没有静态构造函数。

答案 8 :(得分:0)

请参阅my answer一个类似的问题。 C#的静态构造函数隐喻可以用C ++完成。

答案 9 :(得分:0)

我认为静态构造函数用于初始化任何静态数据,或执行仅需要执行一次的特定操作。在创建第一个实例或引用任何静态成员之前,将自动调用它。在++中,我们没有所谓的静态构造函数,但是您可以模仿静态构造函数的功能。看看这个C#静态构造函数:

public class Bus  {
     // Static variable used by all Bus instances.
     // Represents the time the first bus of the day starts its route.
     protected static readonly DateTime globalStartTime;

     // Property for the number of each bus.
     protected int RouteNumber { get; set; }

     // Static constructor to initialize the static variable.
     // It is invoked before the first instance constructor is run.
     static Bus()
     {
         globalStartTime = DateTime.Now;

         // The following statement produces the first line of output, 
         // and the line occurs only once.
         Console.WriteLine("Static constructor sets global start time to {0}",
             globalStartTime.ToLongTimeString());
     }

     // Instance constructor.
     public Bus(int routeNum)
     {
         RouteNumber = routeNum;
         Console.WriteLine("Bus #{0} is created.", RouteNumber);
     }

     // Instance method.
     public void Drive()
     {
         TimeSpan elapsedTime = DateTime.Now - globalStartTime;

         // For demonstration purposes we treat milliseconds as minutes to simulate
         // actual bus times. Do not do this in your actual bus schedule program!
         Console.WriteLine("{0} is starting its route {1:N2} minutes after global start time {2}.",
                                 this.RouteNumber,
                                 elapsedTime.Milliseconds,
                                 globalStartTime.ToShortTimeString());
     }  }

 class TestBus  {
     static void Main()
     {
         // The creation of this instance activates the static constructor.
         Bus bus1 = new Bus(71);

         // Create a second bus.
         Bus bus2 = new Bus(72);

         // Send bus1 on its way.
         bus1.Drive();

         // Wait for bus2 to warm up.
         System.Threading.Thread.Sleep(25);

         // Send bus2 on its way.
         bus2.Drive();

         // Keep the console window open in debug mode.
         System.Console.WriteLine("Press any key to exit.");
         System.Console.ReadKey();
     }  }  /* Sample output:
     Static constructor sets global start time to 3:57:08 PM.
     Bus #71 is created.
     Bus #72 is created.
     71 is starting its route 6.00 minutes after global start time 3:57 PM.
     72 is starting its route 31.00 minutes after global start time 3:57 PM.      
*/

答案 10 :(得分:0)

在C ++中,如果有人说“静态构造函数”,则通常指的是“ static initialization”(和破坏)。使用此术语并不罕见。

答案 11 :(得分:0)

这是c ++ 17中最简单的静态构造函数:

#include <iostream>
class h {
    public:
    static inline int i;
    private:
    struct constructor {
        constructor() {
         i=3;
        }
    };
    static inline constructor cons;
};

int main() {
  std::cout << h::i;
}

答案 12 :(得分:-1)

模拟静态构造函数行为的其他方法是将实例变量与私有构造函数和静态工厂方法一起使用。

Cat* Cat::give_birth() {
  static Cat *myone = NULL;
  if (myone == NULL) {
    myone = new Cat();
  }
  return myone;
}