关闭

浅析C#与C++在静态构造函数上的异同

发表于:2010-1-07 11:20

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:51Testing软件测试网采编

#
DotNet

  这里我们将讨论的是C#与C++在静态构造函数上的异同,通过这一关键点,希望能让大家更好的了解C#与C++,也对大家今后的工作有所帮助。

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

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

  1.静态构造函数既没有访问修饰符,也没有参数
  2.在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类
  3.无法直接调用静态构造函数
  4.在程序中,用户无法控制何时执行静态构造函数

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

  1.class A : static_constructable<A>
  2.{
  3.public:
  4.    static void static_constructor() {
  5.        std::cout << “static constructor a” << std::endl;
  6.        s_string = “abc”; //初始化静态数据
  7.    }
  8.
  9.    static std::string s_string;
  10.
  11.public:
  12.    A(){
  13.        std::cout << “constructor a” << std::endl;
  14.    }
  15.
  16.private:
  17.    int m_i;
  18.};
  19.
  20.std::string A::s_string;
  21.
  22.int _tmain(int argc, _TCHAR* argv[]){
  23.    std::cout << “beginning of main” << std::endl;
  24.
  25.    assert(sizeof(A) == sizeof(int));//继承不改变A的内存布局
  26.    assert(A::s_string == ““);
  27.    A a1;
  28.    assert(A::s_string == “abc”);
  29.    A a2;
  30.    std::cout << “end of main” << std::endl;
  31.
  32.    return 0;
  33.}
  输出:
  34.beginning of main
  35.static constructor a //创建A对象前自动调用静态构造方法,一次且仅一次
  36.constructor a
  37.constructor a
  38.end of main
  下面是static_constructable类模板的实现:
  39.template<typename T>
  40.class static_constructable
  41.{
  42.private:
  43.    struct helper{
  44.        helper(){
  45.            T::static_constructor();
  46.        }
  47.    };
  48.
  49.protected:
  50.    static_constructable(){
  51.        static helper placeholder;
  52.    }
  53.};

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

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

  1. 在第一次构造类对象之前自动调用类提供的静态构造函数
  2. 静态构造函数被调用的时机是确定的
  3. 利用了C++的局部静态变量初始化机制保证了线程安全性(更正:实际并非线程安全,C++标准不涉及多线程问题,而一般编译器实现也非线程安全,更多参见评论部分)
  4. 基于继承的实现机制并未改变派生类的对象内存布局

  不过,和本文开始列出的C#静态构造函数的几个特点相比,本实现还有明显的不足:无法通过调用类A的静态方法触发静态构造函数;类A的静态构造函数必须是public的。希望有更好解决方案的朋友不吝赐教,也欢迎对此话题感兴趣的朋友交流探讨!

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号