第10章 名字控制

  来自C语言中的静态元素

  无论什么时候设计一个包含静态变量的函数时,都应该记住多线程问题。

 

  静态对象的析构函数

  静态对象的析构函数(包括静态存储的所有对象,不仅仅是局部静态对象)在程序从main()中退出时,或者标准的C库函数exit()被调用时才被调用。

  同普通对象的销毁一样,静态对象的销毁也是按与初始化时相反的顺序进行的。当然只有那些已经被创建的对象才会被销毁。

  全局对象总是在main()执行之前被创建,在退出main()时销毁。

 

  控制连接

  所有的全局对象都是隐含为静态存储的,所以如果定义(在文件作用域):

    int a = 0;

  a被存储在程序的静态数据区,在进入main()函数之前,a即已初始化。另外,a对所有的翻译单元都是全局可见的。用可见性术语来讲,static(只在翻译单元内可见)的反义是extern,它明确地声明了这个名字对所有的翻译单元都是可见的。所以上面的定义和下面的定义是相同的:

    extern int a = 0;

  但如果这样定义:

    static int a = 0;

  只不过改变了a的可见性,现在a成了一个内部连接,但存储类型没有改变---对象总是驻留在静态数据区,而不管是static还是extern

  如果把局部变量声明为extern,这意味着某处已经存在一个存储区(所以该变量对函数来说实际上是全局的),如:

    int main(int argc,char* argv[])
    {
        extern int i;

        cout << i << endl;

        return 0;
    }

  如果i在外部没有被定义,会出现连接错误(VS2008):

    error LNK2001: unresolved external symbol "int i" (?i@@3HA)

 

  C++中的静态成员

  定义静态数据成员的存储

  定义必须出现在类的外部(不允许内联)而且只能定义一次,因此它通常放在一个类的实现文件中。

 

  静态成员函数

  静态成员函数不能访问一般的数据成员,而只能访问静态数据成员,也只能调用其他的静态成员函数。通常,当前对象的地址(this)是被隐式地传递到被调用的函数的。但一个静态成员函数没有this,所以它无法访问一般的成员。

 

  在所有的静态对象,连接装载机制在程序员指定的动态初始化发生前保证一个静态成员初始化为零(补充:全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知

 

  替代连接说明

  如果在C++中编写一个程序需要用到C的库,那该怎么办呢?如果这样声明一个C函数:

  float f(int a,char b);

  C++的编译器就会将这个名字变成像_f_int_char之类的东西以支持函数重载(和类型安全转换)。然而,C编译器编译的库一般不做这样的转换,所以它的内部名为_f。这样,连接器无法解释C++f()的调用。

  C++中提供了一个替代连接说明,它是通过重载extern关键字来实现的。Extern后跟一个字符串来指定想声明的函数的连接类型,后面是函数声明:

    extern “C” float f(int a,char b);

  这就告诉编译器f()C连接,这样就不会转换函数名。

  如果有一组替代连接的声明,可以把它们放在花括号内:

  extern “C” {
    float f(int a,char b);
    double d(int a,char b);
  }
原文地址:https://www.cnblogs.com/sheshiji/p/3428541.html