1.综述C++
1.1. 作者
1.2. 历史背景
1.2.1 应“运”而生?运为何?
1.2.2 C++发展大记事
1.3. 应用领域
1.3.1 系统层软件开发
1.3.2 服务器程序开发
1.3.3 游戏,网络,分布式,云计算
1.4. 内容
C++语言的名字,如果看作C的基本语法,是由操作数C和运算符后++构成。C++是本身这门语言先是C,是完全兼容C,
然后在此基础上++。这个++包含三大部分,C++对C的基础语法的扩展,面向对象(继承、封装、多态),STL等。
1.5. 书籍推荐
C++ Primer C++ 编程思想 C++ Priemer Plus
2.C++对C的扩展
2.1. 类型增强
2.1.1 类型检查更严格
比如,把一个const类型的指针赋给非const类型的指针。C语言中可以通的过,但是在C++中则编不过去。
1 #include <iostream> 2 using namespace std; 3 4 int main(int argc, char *argv[]) 5 { 6 const int a = 100; 7 int b = a; 8 9 const int *pa = &a; 10 int *pb = pa; 11 12 return 0; 13 }
error: cannot initialize a variable of type 'int *' with an lvalue of type 'const int *'
int *pb = pa;
1 #include <stdio.h> 2 3 int main(int argc, char *argv[]) 4 { 5 const int a = 100; 6 int b = a; 7 8 const int *pa = &a; 9 //cannot initialize a variable of type 'int *' with an lvalue of type 'const int *' 10 int *pb = pa; 11 12 return 0; 13 }
warning: initializing 'int *' with an expression of type 'const int *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
int *pb = pa;
动态内存分配C/C++区别:
1 #include <iostream> 2 #include <stdlib.h> 3 #include <stdio.h> 4 using namespace std; 5 6 int main() 7 { 8 char *p = malloc(100); //C中可以这样写 9 char *q = (char*)malloc(100); //C中强制类型转换写法 10 11 char *pt = static_cast<char*>(malloc(200)); //C++中强制类型转换写法 12 }
2.1.2 布尔类型(bool)
C语言的逻辑真假用0和非0来表示。而C++中有了具体的类型(bool flag = true/false;),这样的操作,完全可以使用枚举(enum)实现
bool类型在内存中大小等于char类型大小。
2.1.3 真正的枚举(enum)
虽然C中也有枚举,但是在使用的时候,即使赋值不再枚举的范围内,但是依然是可以执行的,但是在C++中,枚举的值必须在枚举的范围内
1 #include <stdio.h> 2 3 int main(void) 4 { 5 enum SEASON{ 6 SPA, SUM, AUT, WIN 7 }; 8 9 enum SEASON s = AUT; 10 enum SEASON r = 100; //这样也可以在C中,在C++这样是不行的 11 return 0; 12 }
2.2. 输入与输出(cin cout)
2.2.1 cin && cout
C中输入典型错误:
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 5 int main() 6 { 7 int a; 8 char c; 9 10 scanf("%d%c", &a, &c); 11 12 return 0; 13 }
这样输入时变量c会读取不到相应的值,因为在输入时我们往往会输入变量a的之后选择空格或者回车符,而变量c接收了空格或者回车符。所以,变量c读取不到对应的值!!!
在C++中,不存在上述问题。(cin >> a >> c;)
注意:
如果定义一个数组,在用这两种输入方式进行输入的时候,都是不安全的,不能保证输入的长度,例如 char name[30]; 用cin>>name;或者使用scanf("%s",name);的时候,如果输入的字符长度超过30个,那么程序就会出错,不过可以使用fgets(name, 30, stdin);这样就指定最多只能接收29个字符(第30个为' '),从而保证了安全性。
虽然通过接收指定长度的操作可以保证程序的安全性,但是这样可能并不能满足用户的需求,所以C++就创造了string,如果将char name[30];改成string name;那么,这个时候就可以不用考虑因为输入过长而导致程序崩溃的问题了(其实是有一个长度的,不过那个长度已经很大很大了,可以通过name.max_size(),这个函数查看),不过这个时候只能使用cin>>name进行输入,而不能使用scanf这个函数了。
2.2.2 格式化
(1) 格式输出的问题
在C语言中,用pringf进行格式输出,可以通过简单的方法,达到丰富的显示效果,在C++中想要达到相同的效果(如果是使用cout)那还是比较麻烦的。以下是对比:
对比 | C语言 | C++ |
设置位宽(n) | printf("%nd ", test); | cout << setw(n) << test << endl; |
左对齐 | printf("%-d ", test); | cout << setiosflags(ios::left) << test << endl; |
设置小数点右边位数(n) | printf("%.nd ", test); | cout << setprecision(n) << setiosflags(ios:: fixed) << test << endl; |
(2) 进制的输出
进制 | C中参数 | C例子 | C++中参数 | C++例子 |
二进制 | ||||
八进制 | %o | printf("%o", 100); | oct | cout << oct << 100 << endl; |
十进制 | 默认 | dec | cout << dec << 100 << endl; | |
十六进制 | hex | cout << hex << 100 << endl; | ||
设置进制 | setbase() | cout << setbase(16) << 100 << endl; |
setbase()参数有指定,如八进制、十六进制
(3) 还可以设置域宽的同时,设置左右对齐及填充字符
1 int main() 2 { 3 cout << setw(10) << 1234 << endl; 4 cout << setw(10) << setfill('0') << 1234 << endl; 5 cout << setw(10) << setfill('0') << setiosflags(ios::left) << 1234 << endl; 6 cout << setw(10) << setfill('-') << setiosflags(ios:: right) << 1234 << endl; 7 8 return 0; 9 }
练习:
时、分、秒的计时器,从00:00:00开始计时,每过一秒计时增加一秒, 秒加到六十时分钟加一,秒又从零开始加;分钟加到六十时小时加一,分钟又从零开始加;小时加到24时,计时器清零变为00:00:00.如此循环计时!!!
2.3 函数重载
2.3.1 引例
2.3.2 重载规则与调用匹配(overload&match)
重载规则:
1. 函数名相同。
2. 参数个数不同,参数的类型不同,参数顺序不同,均可构成重载。(只要满足其一即可)
3. 返回值类型不用则不可以构成重载。
匹配原则:
a.严格匹配,找到则调用
b.如果严格匹配找不到,通过隐式转换寻求一个匹配,找到则调用
注:C++允许,int 到 long 和 double隐式类型转换。double 向 int 和 float进行隐式转换的时候会出现二义性(ambiguous)
解决方案:在调用时强转。
2.3.3 重载底层实现(name mangling)
C++利用name mangling(倾轧)技术,来改变函数名,区分参数不同的同名函数。
实现原理:用v c i f l d 表示 void char int float long double 及其引用。
1 void func(char a); //func_c(char a) 2 void func(char a, int b, double c); //func_cid(char a, int b, double c)
C++的编译方式同C语言,
2.3.4 extern "C"
name mangling 发生在两个阶段,.cpp 编译阶段, 和 .h 的声明阶段。只有两个阶段同时进行,才能匹配调用。
轻轧操作在定义和调用的时候被使用(要么都轻轧,要么都不要轻轧,所以C的库中都使用了extern "C")