谈C 谈cba和nba的差距
创始人
2024-07-31 16:11:52
0

C#中,类的静态构造函数用于在使用类之前进行相关的初始化工作;比如,初始化静态成员或执行特定操作。CLR 在***次创建该类对象或调用该类静态方法时自动调用静态构造函数。同时,CLR保证静态构造函数的线程安全性(准确地说是,只会调用一次,不存在多线程问题)。

下面是MSDN对静态构造函数特点的描述:

1.静态构造函数既没有访问修饰符,也没有参数

2.在创建***个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类

3.无法直接调用静态构造函数

4.在程序中,用户无法控制何时执行静态构造函数

C++语言规范并未包含类似静态构造函数的东西,但在使用类之前做初始化工作的需求却是客观存在的。就满足需求本身来讲,C++完全可以通过手动方式实现,但要处理好初始化时机,线程安全性等问题。本文则尝试通过C++的模版机制模拟实现静态构造函数,避免手动初始化的繁琐实现。对于需要静态构造函数的类A,只需用继承static_constructable模版类,并提供 static void statici_constructor()静态方法即可:

  1. class A : static_constructable  
  2. {  
  3. public:  
  4. static void static_constructor() {  
  5. std::cout << “static constructor a” << std::endl;  
  6. s_string = “abc”; //初始化静态数据  
  7. }  
  8. static std::string s_string;  
  9. public:  
  10. A(){  
  11. std::cout << “constructor a” << std::endl;  
  12. }  
  13. private:  
  14. int m_i;  
  15. };  
  16. std::string A::s_string;  
  17. int _tmain(int argc, _TCHAR* argv[]){  
  18. std::cout << “beginning of main” << std::endl;  
  19. assert(sizeof(A) == sizeof(int));//继承不改变A的内存布局  
  20. assert(A::s_string == ““);  
  21. A a1;  
  22. assert(A::s_string == “abc”);  
  23. A a2;  
  24. std::cout << “end of main” << std::endl;  
  25. return 0;  

输出:

  1. beginning of main  
  2. static constructor a //创建A对象前自动调用静态构造方法,一次且仅一次  
  3. constructor a  
  4. constructor a  
  5. end of main 

下面是static_constructable类模板的实现:

  1. template  
  2. class static_constructable  
  3. {  
  4. private:  
  5. struct helper{  
  6. helper(){  
  7. T::static_constructor();  
  8. }  
  9. };  
  10. protected:  
  11. static_constructable(){  
  12. static helper placeholder;  
  13. }  
  14. }; 

上面的实现把对A::static_constructor()的回调放到内部类helper的构造函数中;并在static_constructable()中定义一个helper局部静态变量;C++保证在构造派生类 A的对象时,会先调用基类static_constructable的构造函数,且静态局部变量只会构造一次,这样就达到调用一次且仅一次A::static_constructor()的目的。

static_constructor类模板简单地模拟了C#的静态构造函数机制,它具有以下特点:

1. 在***次构造类对象之前自动调用类提供的静态构造函数

2. 静态构造函数被调用的时机是确定的

3. 利用了C++的局部静态变量初始化机制保证了线程安全性(更正:实际并非线程安全,C++标准不涉及多线程问题,而一般编译器实现也非线程安全,更多参见评论部分)

4. 基于继承的实现机制并未改变派生类的对象内存布局

不过,和本文开始列出的C#静态构造函数的几个特点相比,本实现还有明显的不足:无法通过调用类A的静态方法触发静态构造函数;类A的静态构造函数必须是public的。

【编辑推荐】

  1. C#初学者对Equals方法的几个常见误解
  2. c#.net实体类序列化方法
  3. 深入C# 序列化(Serialize)、反序列化(Deserialize)
  4. C#中自增、自减操作符重载是个怎么回事儿
  5. C#中的闭包是怎么捕获变量的

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...