Chinaunix首页 | 论坛 | 博客
  • 博客访问: 175694
  • 博文数量: 65
  • 博客积分: 1790
  • 博客等级: 上尉
  • 技术积分: 460
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-21 23:51
文章分类
文章存档

2012年(8)

2011年(38)

2010年(19)

分类: C/C++

2011-02-24 23:48:52

static最基本含义是指“位置不变的某个东西”,这里指内存中的物理位置或文件的可见性。

1,C++从C继承来的2种基本含义:

a,在固定地址上分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次函数调用时在堆栈上产生的。

b,对一个特定编译单元来说是本地的。static控制名字的可见性,这个名字在这个编译单元或类之外是不可见的。

2,函数内部的静态变量

函数体内定义普通变量时,编译器使得每次函数调用时堆栈的指针都向下移一个适当的位置,为这些变量在堆栈中分配内存。

有时想在两次函数调用之间保留一个变量的值,可以通过定义一个全局变量来实现,但这样,这个全局变量不仅仅受这个函数的控制的。

函数内部创建static局部变量,这个变量存储在程序的全局静态数据区中,而不是在堆栈中。

static char* s;

没有为一个预定义类型的静态变量提供一个初始值的话,编译器也会在程序开始时初始化其值为0。

2,函数体内部的静态对象

编译器自动初始化为0只对预定义类型有效,用户自定义类型必须用构造函数来初始化。

3,静态对象的析构函数

静态对象的析构函数在程序从main退出时,或者C标准库函数exit被调用时才被调用。析构函数调用exit是危险的,会陷入死循环。

静态对象的销毁按它们初始化相反顺序进行。编程系统会记录对象初始化的顺序和那些已经被创建的对象。

如果一个包含静态对象的函数从未被调用,则那个静态对象的构造函数不会被执行。

全局静态对象的构造函数在main之前调用的,并且可以在退出main之后用析构函数执行代码。

4,改变变量可见性,所有编译单元可见改变为当前编译单元可见,外部连接改变为内部连接

文件范围内的所有普通对象或函数,对程序中的所有编译单元都是可见的,即外部连接。

文件范围内,声明static的对象或函数对编译单元来说是局部变量,是内部连接。

连接只引用那些在连接/装载期间有地址的成员,因此类声明和局部变量并没有连接。

文件范围内定义:

int a=0;

:::a存储在程序静态数据区,进入main之前已经被初始化。a全局可见,即对所有编译单元可见。

可见性方面static的反义是extern,上面的定义和下面的定义相同

extern int a=0;//a是一个外部连接,所有编译单元可见

static int a=0;//a是一个内部连接,编译单元内可见。

全局变量使用static,存储类型未变,都是静态数据区。static使变量由外部连接改变为内部连接

局部变量使用static,可见性未变,都是内部连接。static使变量存储类型由堆栈改变为静态数据区

函数名使用static,改变可见性

extern void f();//

void f();//可见性同上

static void f();//编译单元内可见。也称为文件静态。

5,名字空间

全局函数、全局变量以及类的名字是在同一个名字空间中。

a,namespace只能在全局范畴定义,可以互相嵌套

b,定义结尾,右大括号后面不必跟一个分号

c,一个namespace可以在多个头文件中用一个标识符来定义

d,未命名名字空间,每个编译单元只有一个未命名名字空间。一个局部名字放在未命名名字空间中,无需加static说明就可以作为内部连接。

f,一个名字空间的类定义之内插入一个friend声明,则它成为名字空间的一个成员。

namespace me{

  class us{

    friend you();//you()成为名字空间me的一个成员

  };

}

6,使用名字空间

2种使用方法:a,范围分解运算符;b,using指令;c,using声明

namespace U{

  void f();

}

namespace V{

  void f();

}

void func(){

  using namespace V;//using directive using指令

  using U::f;//using declaration using声明

  f();//calls U::f()

  V::f();//必须使用全称

}

7,类的静态数据成员-所有类公有的数据成员

类的静态数据成员。拥有一块单独的存储区,所有类对象实例的共享这块静态存储空间,为这些对象实例提供了互相通信的方法。

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

class A{

  static int i;

public:

}

 定义文件中,

int A::i=1;//定义类静态数据成员,这里类名和范围分解运算符用于指定i的范围。

而定义普通全局变量为

int i=1;

8,类的编译时常量

const static常量,即是常量(不会改变)又是静态的(整个类只有唯一一个定义点)。

和全局常量一样,并不会为常量分配存储空间。

9,静态成员函数-所有类公有的成员函数

像静态数据成员一样,也可创建静态成员函数,为类的全体服务而不是为一个类的部分对象服务。这样就不用定义一个全局函数。

静态成员函数不能访问一般数据成员,只能访问静态数据成员,也只能调用其他的静态成员函数。静态成员函数没有this指针。

10,存在依赖关系的静态数据成员初始化

静态对象的初始化顺序严格按照对象在该单元中定义出现的顺序。

存在依赖关系的静态成员初始化易引起问题。

3种方法解决方法:

a,不用它,避免初始化时互相依赖

b,把关键的静态对象定义放在一个文件中,按在文件中的顺序初始化

c,

11,转换连接指定

C++中用到C库,使用 extern "C"

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

其它文章:

1,C++中的static关键字 http://www.vckbase.com/document/viewdoc/?id=1720

2,C/C++中的静态作用详述 http://developer.51cto.com/art/200812/103804.htm

阅读(1399) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~