0、引言
本专栏的系列文章是在学习 北京邮电大学 崔毅东 老师的《C++程序设计 (面向对象进阶)》课程过程中整理的。欢迎前往专栏了解更多相关内容~ 😀
有关于现代 C++ 的基本介绍,请前往《现代C++基本介绍》!
🔔 先决条件
本专栏的系列文章并不适合从未接触过编程的同学,读者需要确保自己已经具备编程基础(特别是 C++ 基础)!您可以参考笔者的「面向对象程序设计(基础)」专栏了解 C++ 基础的相关内容。
1、C++ 源文件与编码规范
1.1、代码文件分类
与 C 语言类似,C++ 的代码文件同样分为两类:
- Header file 头文件
- Source file 源文件
C | C++ |
---|---|
hello.h hello.c | hello.h hello.hpp hello.cpp hello.cxx |
红色标注指的是在一些其他环境中(比如 Linux),后缀名可能会如红色标注所示。
1.2、C++ 编码规范
📌 Why Coding Conventions
为了让程序具备更好的可读性,避免程序难以维护
- Google 开源项目风格指南
- 英文原版
中文版
其中 C++ 规范 5 万多字,过于庞大
- geosoft.no 编码风格指南
- 英文原版
只有英文版,但要相对简明一点
4.9 版本有 94 条规则
在后续的学习中,我们会逐步了解其中一些编码规范
1.3、回望第一个 C++ 程序
在基础阶段我们编写自己的第一个 C++ 程序是一个控制台打印 “Hello World!” 的程序,它的代码如下:
#include <iostream>
using namespace std;int main() {cout << "Hello World!" << endl; return 0;
}
基于这个最简单的 C++ 程序,其实也包含了一些编码规范:
📃 38. Special characters like TAB and page break must be avoided.
📃 38. 必须避免使用“制表”和“分页”等特殊字符因此,在 IDE 中,将“制表符”设置并替换为 4 个空格,可达到同样的缩进效果
📃 68. Functions must always have the return value explicitly listed.
📃 68. 函数必须总是将返回值明确列出在 C++ 中,(只有)返回类型为 int 的函数允许不包含 return 语句,并且不会导致编译错误。此时函数会默认返回一个未定义的值,但这不是一种良好的实践
此外,在这个程序中,我们使用 #include <iostream>
包含了一个头文件。与 C 语言不同,早在 C++98 的时候,包含头文件就没有 .h
后缀了,通常只是包含文件的名称。
1.4、C++ 代码注释
在 C++ 中,可以添加多种注释:
- 行尾注释
- 在代码行的末尾添加注释。这些注释从代码的末尾延伸到行尾
int a = 20; //这是一个行尾注释
- 单行注释
- 以双斜杠
//
开始,知道行尾的内容都被视为注释
//这是一个单行注释
int a = 20;
- 多行注释
- 以
/*
开始,以*/
结束,中间的内容都被视为注释。多行注释可以跨越多行代码
/* 这是一个多行注释 */
int a = 20;
- 文档注释 (Doxygen 风格)
- 通常用于生成文档。以
/**
开头,以*/
结束,可以包含与函数、类、变量等相关的说明文本
/*** @brief 函数说明* @param x 参数 x 的说明* @return 返回值的说明*/
int myFunction(int x){//函数体return x * 2;
}
1.5、Visual Studio 将当前选中项目设置为启动项目
参考 MSDN 运行 C# 项目的介绍
或者
崔毅东老师的教学视频(🧭 第2单元 第02节 2.2演示)
1.6、Visual Studio 设置多个启动项目
参考 MSDN 中的相关介绍
1.7、Visual Studio 对项目进行分组管理
Visual Studio 的解决方案资源管理器支持通过创建“解决方案文件夹”(也称为“解决方案筛选器”)的方式对项目进行分组管理。具体操作可以参考崔毅东老师的教学视频(🧭 第2单元 第02节 2.3演示)
有关“解决方案文件夹”的注意事项
2、命名空间/名字空间 NameSpace
- NameSpace
- 中文译作“ 命名空间”或者“ 名字空间”;比如
std::cout
中的std
就是命名空间。命名空间是一个声明性区域,为其内部的标识符(类型、函数和变量等的名称)提供一个范围。 using 指令 - 通过
using
指令,可使用namespace
中的所有名称,而不需要 namespace-name 为显式限定符。比如我们在 1.3 小节的代码演示。
📌 using namespace std
在 C++ 编程中,通常不推荐直接使用
using namespace std;
,而是更倾向于明确指定命名空间中的标识符,或者使用特定的using
语句,如using std::cout;
或using std::cin;
。这是因为using namespace std;
会引入整个std
命名空间中的所有标识符,可能会导致一些问题和不必要的冲突:
- 命名冲突:
std
命名空间中可能包含与您的程序中的其他命名空间或您自己的代码中的标识符冲突的名称。这可能导致编译错误或不明确的行为。- 可读性和维护性:使用
using namespace std;
可能会使代码更难以阅读和维护,因为您无法轻松地确定来自哪个命名空间的特定标识符。- 潜在的性能问题:引入整个
std
命名空间中的标识符可能会导致编译器需要更多的时间来查找标识符的定义,尤其在大型项目中。
更推荐的做法是使用特定的 using
语句,以引入需要的标识符,例如:
#include <iostream>using std::cout;
using std::endl;int main() {cout << "Hello World!" << endl;return 0;
}
3、编译 C++ 程序的步骤
如下所示流程图展示了创建并编译 C++ 程序的一般步骤:
Precompile
- 预处理/ 预编译,主要做一些代码文本的替换工作
Compile- 编译,将源代码生成机器码 Object file (目标文件), 例如 "Welcome.obj" (Windows 平台)
Link- 链接,将目标文件和外部库链接为一个可执行文件,例如 "Welcome.exe" (Windows 平台)
4、处理错误
- Error Classification 错误分类
-
- Syntax Error 语法错误
- Runtime Error 运行时错误
- Logic Error 逻辑错误
语法错误 -
- 违反了编程语言的语句形式或使用规则,一般由编译器检查指出。
- 例如:遗漏标点符号、错用关键字、分支/循环语句结构缺失等
- 有时也称为“编译错误”
运行时错误 -
- 程序运行时,遇到一个无法执行的操作,一般编译器无法检查指出。
- 例如:执行整数除以 0 的操作、打开不存在的文件、内存不足、磁盘满等
逻辑错误 -
- 程序的运行结果与预期的正确结果不一致,编译器无法检查指出。
- 例如:将 10 个整数排序输出的结果是由小到大,但是预期结果是由大到小
📌 常见的语法错误
- 写错关键字;
- 遗漏分号;
- 遗漏大/中/小括号;
- 遗漏引号等;
#includ <iostream> //写错关键字 using namespace std //遗漏分号//函数名写错 int mian() { cout << "Hello World!" << endl; cin.get); //遗漏小括号return 0; //遗漏大括号
4.1、与 namespace 有关的错误
- 未使用
using
语句而直接使用命名空间下的标识符,将会导致“未定义的标识符”错误。 - 我们可以声明自己的命名空间和命名空间成员,参考 MSDN。但需要注意的是,我们不能将
main
函数也包含在自己声明的命名空间当中,这样会导致“无法找到应用程序的主入口点”(参考 StackOverflow 了解更多)。
5、输入与输出
输入输出分类(根据源目分类):
- Standard I/O(标准 IO):从键盘输入信息,在屏幕上显示信息;
- File I/O(文件 IO):从文件中读信息,将信息写入到文件;
- String I/O(字符串 IO):从字符串中读信息,将信息写入到字符串;
- Network I/O(网络 IO):通过网络发送、接收信息;
作为初学者,我们通常最关注的是 标准输入输出。
📌 C 和 Java 语言中的输入输出
Input 输入 Output 输出 C scanf()
getchar() / gets()printf()
putchar() / puts()Java Scanner 类
…System.out.println() / print() / printf() / …
5.1、C++ 输入输出
C++ 使用一种称为 “流” (stream) 的概念对屏幕、键盘或者文件进行输入输出操作
Stream 流 | Description 描述 |
---|---|
cin | standard input stream 标准输入流 |
cout | standard output stream 标准输出流 |
cerr | standard error (output) stream |
clog | standard logging (output) stream |
📌 小知识
cin
和cout
中的c
指的是 “character”,而不是 C/C++。
Stream 流 | Operators 操作符 | Functions 函数 |
---|---|---|
cin | >> 含义:extraction operator (流提取运算符) | cin.get() 从流中读并取走一个字符 cin.getline() 从流中读取字符,直至行尾或指定的分隔符 cin.ignore() 从流中读取并舍弃指定数量的字符 |
cout | << 含义:insertion operator (流插入运算符) | cout.put() 将字符写到流中(无格式) cout.flush() 将流中缓存内容全部输出 |