c++ 编程拾贝(三)

来源:互联网 发布:端口打开失败怎么回事 编辑:程序博客网 时间:2024/04/29 14:13

c++ 编程拾贝(三)

第10章 名字控制

静态对象的析构函数

是从main()中退出时,或者从c的exit()库函数被调用时才被调用(多数情况下,mian()函数的结尾也是通过调用exit()函数来退出main()程序的)

而这里有个潜在的风险,也即如果在静态函数中加入了exit()函数,会发生无穷地递归调用。这里,如果调用c库函数的abort()来退出程序,静态析构函数不被调用

abort():    异常终止某一个进程,关闭所有的流

这里还提到一个atexit()函数,用来指定main()函数退出前,exit()函数调用前应执行的操作。

atexit()    用来注册函数,在main()调用exit()之后,由exit()函数调用

控制连接

外部连接:文件作用域文件间是互相可见的,但是局部函数内、类中的名字不算在文件作用域中

对于只想让本文件作用域内的函数或者类使用,而不想被其他文件访问,可以申明成staticstatic只能内部连接,具有文件隔离性质,其他文件单元作用域可以有同名的定义而不冲突。

注意,这里const在c++中也是默认的内部连接的,而在c中则是外部连接的。

连接只涉及到那些在连接/装载期有地址的成员(const在c++中默认是无地址的)因此类声明和局部变量并不连接(它们都是运行时分配内存)。

关于extern,static

这里涉及到一个冲突的问题,我们先看这样的在作用域中的定义:

int a = 0;int main(){    .......}

这里的a隐式地被声明为静态存储的,存储在静态区,而想要其他编译单元可见,则只能这样定义它:

extern int a = 0;

而不管内部连接、外部连接,只要在全局区域定义的变量,都会在连接期之前确定内存区域(静态内存区)

而一旦进入了局部变量static就不会再改变变量的可见性,只改变变量的存储类型。

如果把局部变量声明为extern,这意味着告诉编译器放行,该变量意境存在在一个存储区(对于包含该局部变量的函数来说该变量是全局的),举个例子:

#include<iostream>using namespace std;int main(){    extern int i;    cout<<i<<endl;}int i = 5;

而对于给函数名添加static或者extern属性,只会改动该函数的可见性。我们来看两个例子

extern void f(); //******1static void p(); //******2

对于f()来说声明为extern与没有extern是一样的,而对于p()来说,则该函数只能在本文件内使用。

名称空间

创建一个名称空间:

namespace Mylib{    //declaration}

这里谈一谈namespace的注意点

  • namespace 只能在全局区域定义,允许嵌套namespace
  • namespace 跟类、结构体、enum不同的地方就是它不用在括号后面跟上分号
  • 定义可以在不同文件中重定义
  • 也可以取一个别名,使用方法:
namespace BobsSuperDuperLibrary{    class Widget{};    class Poppit{};}//aliasnamespace Bob = BobsSuperDuperLibrary;int main(){}
  • 这里不能像类那样去实例化一个名称空间实例
  • 名称空间允许一个友元,将友元函数放入该名称空间

至于名称空间的使用,使用using或者域作用符即可。
这里的using可以理解为将using后面的名称空间内的所有内容引用到当前名称空间,嵌套在当前名称空间。
甚至可以在函数内部引用名称空间。

using带来的一个可能的问题是二义性的问题,发生二义性是发生在使用名称的时候,而不是在using的时候。这其实就是一个很难发现的潜在问题。

还有一个有意思的是,如果名称空间里有重载函数

//File Anamespace FooSpace{    void foo();    int foo(int);}//File Bint main(){    using namespace FooSpace::foo;}

如果在另外的文件里声明引用里FooSpace里的foo函数,这里会将所有的重载函数同时引进。

在这里有一个建议是,using namespace放在cpp文件里,而不要放在一个头文件里,因为引用该头文件时可能会造成名称空间的污染。

1 0
原创粉丝点击