C++对C的扩展
::作用域运算符
通常情况下,如果有两个同名变量,一个是全局变量,一个是局部变量,那么局部变量在其作用域中有较高的优先权, 它将屏蔽全局变量(就近原则)
代码示例
#include <iostream> #include <string> #include <iostream> using namespace std; int a = 10; void test() { int a = 20; cout << a << endl; cout << ::a << endl; } int main(int argc, char* argv[]) { test(); return 0; }
namespace 命名空间
在C++中,名称可以是符号常量、变量、函数、结构、枚举、类和对象等。工程越大,名称相互冲突的可能性越大。另外使用多个厂商的类库时,也可能导致名称冲突。为了避免在大规模程序设计中,以及在程序员使用各种各样的C++库的时候,这些表示符的命名发生冲入,标准的C++引入关键字namespace,可以更好的控制标识符的作用域。
代码示例
#include <iostream> #include <string> #include <iostream> using namespace std; namespace A { int a = 10; namespace C { int a = 200; } void c() { cout << "A :: C" << endl; } } namespace B { int a = 20; void c(); } void B::c() { cout << "B :: C" <<endl; } void test() { cout << A::a << endl; cout << A::C::a << endl; cout << B::a << endl; A::c(); B::c(); } int main(int argc, char* argv[]) { test(); return 0; }
命名空间的使用注意
- 命名空间只能在全局范围定义
- 命名空间内可以嵌套命名空间
- 命名空间是开放的,可以随时把新的成员加入已有的命名空间中
- 命名空间可以存放变量、函数、类等
- 命名空间中的函数可以在命名空间外部定义
无名命名空间和命名空间别名
意味着命名空间的标识符只能在本文件内访问,相当于给这个标识符加上了static,使得其可以作为内部连接
#include <iostream> #include <string> #include <iostream> using namespace std; namespace { int a =300; void func() { cout << " im 啊" <<endl; } } namespace vewrylongnamespace { void func() { cout << "vewrylongnamespace" <<endl; } } void test() { cout << a << endl; func(); namespace aa = vewrylongnamespace; aa::func(); } int main(int argc, char* argv[]) { test(); return 0; }
using声明
- 表示从using开始,下面的变量使用using声明的命名空间中优先获取,简化对命名空间成员访问的操作。
- 简化的代价是容易造成命名空间的冲突。
- using 指明使用具体的命名空间的成员。如果出现冲突则会报错,不会和全局变量冲突。
- using遇到函数重载的时候,指定函数会对所有的函数起作用。
#include <iostream> #include <string> #include <iostream> using namespace std; namespace A { int a = 10; } namespace vewrylongnamespace { int a = 20; } void test() { // int a = 100; using namespace A; // using A::a; cout << a << endl; } int main(int argc, char* argv[]) { test(); return 0; }
#include <iostream> #include <string> #include <iostream> using namespace std; namespace B { int a = 20; void func() { cout << "B" <<endl; } void func(int a) { cout << "func with a" <<endl; } } void test() { using B::func; func(1); } int main(int argc, char* argv[]) { test(); return 0; }
注意: 不同命名空间的同名成员使用的时候注意二义性。
语法的增强
- 全局变量的增强检测
- 类型检查增强,函数参数和返回值必须有类型,不可以缺省
- 严格的类型转换
- struct类型加强
struct的增强
- C中定义结构体在使用的时候需要加上struct关键字, C++不需要
- C中的结构体只能定义变量,不能定义成员函数, C++都可以
bool 类型
标准C++的bool类型有两种内建常量(true 和false)表示状态,占一个字节大小,只有两个值
C99之后才有和C++一样的bool值。
三目运算符
C语言三目运算符返回的为数据值,为右值,不能赋值
C++返回的为变量本身(引用), 为左值,可以赋值
const 关键字
C语言
- const 修饰全局变量,内存空间在文字常量区(属于全局区,只读),不能通过num的地址修改空间内容。
- const修饰局部变量时,变量名只读,内存在栈区(可读可写),可以通过变量的地址间接修改空间内容。
C++
- 在C++中一个const不必创建内存空间,是否分配依赖于如何使用;而在C中一个const总是需要一块内存空间。
- 在函数之外的const默认是内部连接,在其他文件无法访问。如果想在别的文件中使用则必须加extern。
- C++中对于基础类型,系统不会给data开辟空间,系统会把数据放入符号表中,data可以看成真正的常量。
- 对data取地址的时候,系统会给data开辟内存空间。
- 使用一个变量给只读变量初始化的时候也会开辟空间,这种情况下不会将const变量放入符号表中,因此可以修改其值。
- 对于自定义数据类型,也会开辟空间。
- 尽量使用const替换宏。
#include <iostream> #include <string> #include <iostream> using namespace std; void test() { const int data = 10; cout << data << endl; int *p = (int *)&data; *p = 2000; cout << *p << endl; cout << data << endl; int a = 10; const int b = a; int *pp = (int *)&b; *pp = 200; cout << *pp << endl; cout << b << endl; } int main(int argc, char* argv[]) { test(); return 0; }
const 替换define
- const 有类型,可以进行编译器类型安全检查,#define没有类型,不会进行类型检查
- const有作用域,而#define没有作用域,默认到文件末尾都是有效的
引用
引用是C++对C的重要扩充。在C/C++中,指针的作用基本都是一样的,但是在C++中增加了另外一种给函数传递地址的途径,这就是按引用传递,它也存在于其他语言中,不是C++发明的。
语法:
- &和别名结合表示引用
- 给某个变量取别名,就定义某个变量
- 从上往下替换
int num = 10; int &a = num; // 表明a是引用变量, a是num的别名
注意:
- 引用必须初始化
- 一旦初始化,不能随便修改
C++对C的扩展(下):https://developer.aliyun.com/article/1459383