C++中static的含义及名字控制
1、C/C++中,static有两层含义:在固定的地址上进行存储分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次函数调用时在堆栈上产生的。第二层含义是:对一个特定的编译单位来说是局部的。
静态对象的析构函数在main函数退出时,或是标准的C库exit()被调用时才被调用。在C++中,全局静态对象的构造函数在是main之前执行的。
2、外部连接与内部连接
一般来说,在文件作用域内的所有名字对程序中的所有翻译单元都是可见的,这就是外部连接(external linkage)。全局变量和普通函数是外部连接。
被声明为static的对象或函数的名字对翻译单元来说是局部于该单元的,这就是内部连接。如常量,内联函数,在默认情况下都是内部连接的。注意连接只引用那些在连接/装载期间有地址的成员,因此类声明和局部变量并不连接。
全局变量和静态变量存放在静态存储区。
对函数名(非成员函数),static与extern只会改变它们的可见性。
一个namespace可以在多个头文件中用一个标识符来定义。
//: C10:Header1.h
#ifndef HEADER1_H
#define HEADER1_H
namespace MyLib {
extern int x;
void f();
// ...
}
#endif // HEADER1_H ///:~
//: C10:Header2.h
#ifndef HEADER2_H
#define HEADER2_H
#include "Header1.h"
// Add more names to MyLib
namespace MyLib { // NOT a redefinition!
extern int y;
void g();
// ...
}
#endif // HEADER2_H ///:~
确保每个翻译单元只有一个未命名的名字空间,如果把一个局部名字放在一个未命名的名字空间中,不需要加上static就可以作内部连接。
3、使用命名空间的三种方法:
1)作用域解析
2)使用指令using directive:只有文件编译时才起作用。
3)使用声明using declaration
Using声明给出了标识符完整的名字,但却没有了类型方面的信息。如果包含一组相同名字重载的函数,则声明了这个重载的集合内的所有函数。
不要把一个全局的using指令引入到一个头文件中。在头文件中,最好使用明确的限定或被限定在一定范围内的using指令和using声明。
class X {
private:
int i;
public:
X(int ii) : i(ii) {}
};
class Stat {
static X x2;
static X xTable2[];
static const X x3;
static const X xTable3[];
};
X Stat::x2(100);
X Stat::xTable2[] = {X(1), X(2), X(3), X(4)};
const X Stat::x3(100);
const X Stat::xTable3[] = {X(1), X(2), X(3), X(4)};
int main()
{
Stat v;
return 1;
}
4、嵌套类和局部类
把一个静态数据成员放入在另一个类的嵌套类中。然而不能在局部类(在函数内部定义的类)中有静态数据成员。
如下一个例子,把构造函数定义为私有的,这样Egg类只能有唯一的对象存在。
#include <iostream>
using namespace std;
class Egg {
static Egg e;
int i;
Egg(int ii) : i(ii) {}
Egg(const Egg&); // Prevent copy-construction
public:
static Egg* instance() { return &e; }
int val() const { return i; }
};
Egg Egg::e(47);
int main() {
//! Egg x(1); // Error -- can't create an Egg
// You can access the single instance:
cout << Egg::instance()->val() << endl;
} ///:~ ///:~
5、替代连接说明
C++中,float f(int a, char b);会被编译成_f_int_char来支持函数重载和类型安全连接,而C却不这么做,它的内部名为_f。就样连接器无法解释C++对f()的调用。
C++中用alternate linkage specification(通过重载extern关键字来实现)来解决这个问题。格式如下:
extern "C" float f(int a, char b);
告诉编译器f()是C连接。标准的连接类型有"C""C++"。
如果有一组替代连接声明,则放在花括号内:
extern "C" {
float f(int a, char b);
double d(int a, char b);
}
Or, for a header file,
extern "C" {
#include "Myheader.h"
}
附:
友元、静态成员
http://blog.163.com/zhoumhan_0351/blog/static/39954227201002621251123
C++发展后期增加的工具
http://blog.163.com/zhoumhan_0351/blog/static/3995422720101247214441