C plus plus -- C语言的超集
C++可以完全引用C
案例:输出Hello World
- 源代码:
HelloWorld.cpp
// 第一个C++程序
#include <iostream>
using namespace std;
int main(){
cout<< "Hello world" <<endl;
}
- 编译:
g++ HelloWorld.cpp -o HelloWorld - 执行:
./HelloWorld - 结果:
Hello world
麻雀虽小,五脏俱全。
从HelloWorld.cpp,看C++与C的基本区别:
- 单行注释
//(C99开始支持单行注释) - 文件后缀名
.cpp - 头文件
#include <iostream> - 命名空间
using namespace std; - 标准输出流
cout、输出运算符<<、换行控制器endl - 编译工具
g++
1. 源文件后缀
- C/C++头文件后缀名区别
| C | C++ |
|---|---|
*.h |
*.h *.hpp
|
- C/C++源文件后缀名区别
| C | C++ |
|---|---|
*.c |
*.cpp *.cc *.cxx
|
- 不同编译器C++源文件后缀名区别
| 平台 | 可用后缀名 |
|---|---|
| Unix |
*.C, *.cc, *.cxx, *.c
|
| GNU C++ |
*.C, *.cc, *.cxx, *.cpp, *.c++
|
| Borland C++ | *.cpp |
| Microsoft Visual C++ |
*.cpp, *.cxx, *.cc
|
2.引用头文件
C++头文件使用C标准库,在C标准库文件名前加上字母c,并且省略后缀名.h,例如:
| C | C++ |
|---|---|
#include <stdio.h> |
#include <iosteam> /#include <cstdio>
|
#include <stdlib.h> |
#include <cstdlib> |
#include <string.h> |
#include <cstring> |
#include <math.h> |
#include <cmath> |
有些C++编译器同时支持以上两种头文件,但有些不。请使用C++标准方式
3. 函数重载
实验: 以下C与C++的编译执行结果
printf.c
#include <stdio.h>
void printf(){
printf("Hello world");
}
int main(){
printf();
}
printf.cpp
#include <cstdio>
void printf(){
printf("Hello world");
}
int main(){
printf();
}
函数重载:函数名相同只有参数(个数或者类型)不相同。
| C | C++ |
|---|---|
| 不支持重载 | 支持重载 |
4. 命名空间
实验: 以下C的编译结果
scope.c
#include <stdio.h>
void test(){
printf("this is test\n");
}
void test(){
printf("this is another test\n");
}
int main(){
test();
}
命名空间
| C | C++ |
|---|---|
| 不支持命名空间 | 支持命名空间 |
命名空间的作用:避免全局变量、函数、类的命名冲突(因为名字相同而编译失败)。
定义命名空间
namespace 空间名 {
// 定义类/函数
}
- 引用命名空间
- using指令(using directive)
例如使用标准命名空间using namespace 空间名;stdusing namespace std; - using声明(using declaration)
例如使用标准命名空间using 空间名::标识符;std的coutusing std::cout;
- using指令(using directive)
C++命名空间处理方式
#include <cstdio>
namespace scope1 {
void test(){
printf("this is test\n");
}
}
namespace scope2 {
void test(){
printf("this is another test\n");
}
}
int main(){
scope1::test();
scope2::test();
}
全局命名空间
- 默认的命名空间,所有名字都在全局命名空间中。
- 使用方式:直接忽略或者只写
::
例如:定义全局函数void test();,默认就是在全局命名空间中,调用方式test()或者::test()。
在C++中,不带
.h后缀的头文件所包含和定义的标识符在std空间中;
带.h后缀的头文件所包含和定义的标识符在全局命名空间中,不需要声明使用std空间
5. 类型
- 新增基本类型
bool--true/false
在C99中
stdbool.h中增加三个宏定义bool、true和false。在C++中是内置类型和常量。
如何验证C的bool是宏定义,C++的bool不是宏定义?
password.c
#include <stdio.h>
int main(){
printf("input user name:");
char name[BUFSIZ];
scanf("%s",name);
printf("input 3 number password:");
int password1;
scanf("%d",&password1);
printf("input 3 number password again:");
int password2;
scanf("%d",&password2);
printf("password check:%d\n", password1 == password2);
}
password.cpp
#include <iostream>
#include <cstdio>
using std::cout;
using std::cin;
using std::endl;
int main(){
cout << "input user name:";
char name[BUFSIZ];
cin >> name;
cout << "input 3 number password:";
int password1;
cin >> password1;
cout << "input 3 number password again:";
int password2;
cin >> password2;
cout << "password check:" << (password1 == password2) << endl;
}
- 新增自定义类型
class
详细信息参见:类与对象章节
6. 思想
| C | C++ |
|---|---|
| 面向过程 | 面向对象/基于对象 |
何为面向过程?何为面向对象?
- 面向过程:强调如何处理(如何解决)
- 面向对象:强调执行处理的对象(找谁解决)
面向过程与面向对象:厨师与老板
思维区别
- 将问题按照过程方式来解决?
- 将问题抽象为一个对象来解决?
7. 动态内存
- 基本类型的动态内存
dynamic_mem.c
#include <stdio.h>
#include <stdlib.h>
int main(){
int* num = malloc(sizeof(int));
*num = 100;
printf("%d\n",*num);
free(num);
}
dynamic_mem.cpp
#include <iostream>
int main(){
int* num = new int;
*num = 100;
std::cout << *num << std::endl;
delete num;
}
动态内存区别
| C | C++ |
|---|---|
malloc()/free()
|
new/delete
|
C++仍然可以使用malloc()/free(),但是不建议这么做。
问题:
-
malloc()申请内存,是否可以使用delete销毁内存? -
new申请内存,是否可以使用free()销毁内存?
8. 初始化
C++特殊初始化方法
int n=10;
int m(10);
扩展阅读
-
<<Accelerated C++中文版>> 第0~2章
- 为什么
for循环的下标习惯从0开始? - 为什么
for循环的的判断条件通常使用!=?
- 为什么
-
<<C++程序设计原理与实践>>
- 第2章Hello,World!
- 第3章 对象、 类型和值
练习
- 完成上面扩展阅读中的习题和练习。