2、const
• 指名其修饰对内容保持不变,用于:标识变量和标识方法
• cosnt修饰变量
1、代替#define来定义常量
2、const int* p=NULL 《==》int const* p=NULL
const应用于紧挨着const左侧的第一项。
3、const int&和int const&是等价的;C++不允许使用const声明引用,因为引用本身就是常量
int z;int& const refInt=z; //WRONG!!!
• const方法
在类里面声明方法使用const,可用于防止对数据成员的修改
3、static
static有三种不相关的用法:
• static数据成员和方法,表示该成员或方法归类所有,所有对象共用一个;
• static链接
先了解一下C++中链接linkage的概念。C++中每个源文件是独立编译的,得到的对象文件要链接在一起。C++源文件中的每个名字,包括
函数和全局变量,都有一个链接,可能是内部internal链接,也可能是外部external链接。外部链接是指,对于其他源文件,这个名字是可用的。内部链接(也称为静态链接static linkage)是指,对于其他源文件,这个名字不可用。函数和全局变量默认都是外部链接。但是,可以在声明前面加上static,来指定为内部/静态链接。
比如:
//FirstFile.cpp
void f(); //prototype declare
int main()
{
f();
return 0;
}
//AnotherFile.cpp
void f();
void f()
{
cout<<"f()/n";
}
...
因为函数和全局变量默认为外部链接,所以,在FirstFile.cpp里面对f()的调用成功;
但是如果把AnotherFile.cpp中的f()声明加上static:
static void f();
这时,在FirstFile.cpp里面就不再可以调用。 C++委员会已经意识到static的意思太过丰富,所以,不建议使用static,来声明内部链接。
相同的方法:匿名命名空间anonymous namespace来保证函数或全局变量为内部链接:
//AnotherFile.cpp
namespace {
void f();
void f()
{
cout<<"f()/n";
}
}
...
使用匿名命名空间以后,就只能在该文件中中访问。
与static相反的就是extern关键字了。
注意,把一个名字指定为extern时,编译器会把它当作声明而不是定义。对于变量来说,这意味着编译器不会给变量分配空间。必须提供没有extern的变量定义,或函数定义。
如:
//another.c
extern int x; //若写成extern int x=3,编译器会有warning
int x=3;
//first.c
#include <stdio.h>
extern int x; //如果没有这一句会提示x未定义
int main( )
{
printf("%d/n",x );
return 0;
}
编译命令:
gcc -Wall first.c another.c -o first
注意:在实际的项目中不建议使用全局变量,具有迷惑性。
• 函数中的static
用于创建局部变量,通常用于记录是否已经为一个函数进行特定的初始化。
void perfrom( )
{
static bool inited=false;
if( !inited )
{
//perform initialization
inited=true;
}
...
}
• 不同文件中非局部变量的初始化顺序并不确定
程序中所有的全局变量和static类数据成员都是在main之前初始化的。不同文件中非局部变量的初始化顺序并不确定,所以当不同文件中对非局部变量的初始化需要另外的非局部变量时,可能会出现依赖死锁。
4、类型转换
• const_cast用于删除常量属性
• static_cast用于显示的完成C++语言直接支持的转换,如int/float/char;static_cast还可以用于在继承层次结构中完成向下类型强制转换。
• reinterpret_cast比static_cast更强,但安全性较低。满足以下类型转换:
按照C++类型规则来说,从理论上讲这种转换是不允许的,但是在某种场合下它们对程序员可能很有意义。例如,可以把一种指针或引用转换成另外的一种指针或引用,即使在继承层次不相关也可以;还可以把指针转换成int,或者int转换成指针。在使用reinterpret_cast的时候要格外小心,因为它会把原始的位bit重新解释为不同的类型,却不会进行类型检查。
• dynamic_cast进行转换时,会进行运行时类型检查,运行时类型信息是存储在对象的vtable里面的。因此使用dynamic_cast,类必须至少有一个虚函数。