首页 > OOP语言 > C++ > 正文

由struct的静态构造函数说起
2011-10-20 00:00:00   来源:www.bianceng.cn   评论:0 点击:

暂时无描述信息

最近才知道struct和class的静态构造函数的触发规则是不同的,不像class在第一次使用类的时候触 发静态构造函数。如果只访问struct实例的字段是不会触发静态构造函数调用的。通过测试发现当访问静 态字段,struct本身的函数(静态和实例)和带参数的构造函数就会引起静态构造函数的执行。而调用默 认构造和未覆写的基类虚函数是不会的。为什么呢?

让我们先来看看class和struct在调用构造函数时的区别。class使用newobj指令而struct使用initobj 指令来构造对象。newobj在堆上申请一块内存并调用相应的构造函数进行初始化,然后将对象地址返回给 计算栈。initobj则是从本地变量表中载入已经分配出来的struct实例然后初始化struct的各字段。这个 初始化过程是CLR内部执行的,而不像class编译器会给class添加一个默认构造函数(这就是为什么 struct不能给字段添加默认值的原因。但在类中如果给字段添加了默认值编译器就会自动在构造函数中添 加字段赋值操作)。如果给struct中定义了一个有参数的构造函数,那么系统就不会使用initobj指令, 而是直接用call指令调用带参数的构造函数。

我们最常见最常用的调用函数的指令是call和callvirt。对于静态函数使用call指令,对于class使用 callvirt指令(不论class中的函数是不是虚的)。只有子类调用父类的函数的时候(避免递归调用)以 及构造函数中(由编译器添加保证父类字段被初始化)使用call指令。而对于struct我们发现只要调用的 函数是struct本身定义的都是使用call指令。call和callvirt指令的差别在于,call会把调用的函数当作 静态函数看待,而不会关心调用当前函数时实例指针(this)是否为空。这就是struct调用函数时为什么 都是call因为struct实例是不可能被置为null的。实际上class在调用非虚函数时实际上也是使用call的 只是多做了一步验证——this是否为空,让我们来验证一下。

class Class_Test
{
  public void Test1() {}
  public virtual void Test2() {}
  public static void Test3() {}
  public override string ToString()
   {
    return base.ToString();
  }
}
Class_Test c = new Class_Test ();
c.Test1();
c.Test2();
Class_Test.Test3();
string str = c.ToString();

相关热词搜索:

上一篇:Boost库中的实用工具类使用入门
下一篇:图文教程:在Eclipse下安装C++插件CDT

分享到: 收藏