第 1 章 开始
1.1 一个简单的 C++ 程序
>> 概念:函数
函数的定义将包含 4 个部分:返回类型(return type
函数名(function name ) 、 一个括号包围的形参列表(parameter list)以及函数体(function body ) 、 ) 。 一个程序将包含多个函数,其中 main 函数将会被系统主动调用来执行程序功能。
NOTE
main 函数的返回类型必须是 int,即整数类型
1.2 输入 & 输出
C++ 并未定义任何输入输出语句,但是其包含的全面的标准库提供了 IO 机制。
例如 iostream 库,其包含 istream 输入流与 ostream 输出流。
>> 概念:流
流就是一个字符序列,从 IO 设备读出或写入 IO 设备的,流(stream)想表达的意思是:随着时间的推移,字符是顺序生成或消耗的。
标准库中提供了 4 个输入输出对象:cin、cout、cerr 与 clog
通常使用 cerr 来输出警告信息,而 clog 来输出程序运行时的一般性信息。
1.2.1 向流写入数据
#include <iostream>
int main() {
std::cout << "Hello"
<< " "
<< "World" << endl;
return 0;
}
从本质上理解,cout 作为一个 IO 对象,其后应该是一个表达式,而这个表达式用到了 <<
输出运算符:<<
运算符接受两个对象,一个是左边的 ostream 对象,另一个是右边的待打印对象,并且返回左侧的 ostream 对象,<<
运算符从左到右依次执行,来依次打印每一个输出对象,直到最后剩下一个单独的 ostream 对象,因此,上述代码等价于:
#include <iostream>
int main() {
(std::cout << "Hello"
<< " "
<< "World")
<< endl;
return 0;
}
1.2.2 从流读取数据
#include <iostream>
int a, b;
int main() {
std::cout << "Enter two numbers:" << endl;
std::cin >> a >> b;
return 0;
}
cin 是另一个 IO 对象,用于接收 istream 输入流,同时我们用到了 >>
输入运算符,他从左侧接受一个 istream 对象,并存入右侧对象中。
1.3 注释
#include <iostream>
int a, b;
int main() {
std::cout << "Enter two numbers:" << endl;
// 输出提示
std::cin >> a >> b;
/*输入参数*/
return 0;
}
C++ 支持两种注释语句://
行内注释 与 /**/
跨行注释。
跨行注释不可嵌套。
NOTE
编译器会忽略注释,但是开发人员不会,并且会倾向于相信其正确性,所以请及时为你的程序加上或更新注释,记住:没有注释的程序已经够糟糕了,但错误 / 过时的注释比完全没有注释更糟糕!
1.4 命名空间
1.4.1 名字空间的定义
名字空间是 C++ 提供的一个用于防止命名冲突的机制。通过名字空间,可以将不同作用域中的同名实体(如变量、函数、类等)区分开来,避免不同库或模块中的相同名称互相冲突。
namespace myNamespace {
int num = 42;
void display() { std::cout << "Hello from myNamespace!" << std::endl; }
} // namespace myNamespace
在这个例子中,num
变量和 display
函数都属于 myNamespace
命名空间。
1.4.2 使用名字空间中的成员
要使用某个名字空间中的变量或函数,可以通过作用域运算符::
进行限定。
例子
std::cout << myNamespace::num << std::endl; // 输出:42
myNamespace::display(); // 输出:Hello from myNamespace!
1.4.3 using
声明
如果频繁使用某个名字空间中的单个成员,可以使用 using
声明,将特定名字空间中的成员引入当前作用域,以简化代码。
using myNamespace::num;
std::cout << num << std::endl; // 输出:42
使用 using
声明后,直接使用 num
即可,而不需要写 myNamespace::num
。
1.4.4 using
指令
using namespace
指令可以将整个名字空间引入当前作用域,从而不需要再对每个成员使用限定符。不过,这样做可能会导致名字冲突。
using namespace myNamespace;
std::cout << num << std::endl; // 输出:42
display(); // 输出:Hello from myNamespace!
1.4.5 标准库的名字空间
C++ 标准库中的所有内容都在 std
命名空间中。因此,在使用标准库的任何对象时,通常需要加上 std::
前缀,例如 std::cout
、std::string
等。
std::cout << "Hello, World!" << std::endl;
std::string str = "C++ Primer";
1.4.6 名字空间的嵌套
名字空间可以嵌套定义,从而形成分层的作用域结构。
cpp复制代码namespace outer {
namespace inner {
int value = 10;
}
}
std::cout << outer::inner::value << std::endl; // 输出:10
1.5 控制流
1.5.1 条件语句
C++ 的条件语句包括 if
、else if
和 else
。
if (score > 90) {
std::cout << "Excellent" << std::endl;
} else if (score > 75) {
std::cout << "Good" << std::endl;
} else {
std::cout << "Needs Improvement" << std::endl;
}
NOTE
避免过度嵌套的条件语句 为了使代码更清晰易懂,尽量减少过度嵌套的条件语句。例如,如果可以提前返回或退出循环,尽量选择这种方式来避免不必要的嵌套。
1.5.2 switch 语句
switch
语句用于多分支条件选择,在需要根据某个表达式的不同值执行不同操作时非常有用。
switch (grade) {
case 'A':
std::cout << "Excellent" << std::endl;
break;
case 'B':
std::cout << "Good" << std::endl;
break;
case 'C':
std::cout << "Pass" << std::endl;
break;
default:
std::cout << "Fail" << std::endl;
break;
}
NOTE
别忘了使用 break
,switch
语句中,别忘了在每个 case
后使用 break
语句。如果省略 break
,控制流会继续执行后续的 case
代码,直到遇到 break
或 switch
语句结束。这种行为叫做贯穿,在某些情况下可能有用,但大多数情况下是不希望发生的。
1.5.3 循环结构
C++ 中有三种主要的循环结构:while
、do-while
和 for
循环。
while
循环
int i = 0;
while (i < 5) {
std::cout << i << std::endl;
++i;
}
do-while
循环
int i = 0;
do {
std::cout << i << std::endl;
++i;
} while (i < 5);
for
循环
for (int i = 0; i < 5; ++i) {
std::cout << i << std::endl;
}
NOTE
选择合适的循环结构 while
循环在循环前先判断条件,而 do-while
循环则是先执行一次再判断条件。因此,当你需要确保循环体至少执行一次时,选择 do-while
循环。如果知道循环次数,for
循环通常更适合。(例外:一些 OI 题中会有多组测试数据,为了避免占用常用的循环变量 i,最大层循环通常使用 while(t--)
的形式完成)
1.5.4 break 和 continue
break
用于提前终止循环。continue
用于跳过当前循环的剩余部分,直接进入下一次循环迭代。
for (int i = 0; i < 10; ++i) {
if (i == 5)
break; // 终止循环
std::cout << i << std::endl;
}
for (int i = 0; i < 10; ++i) {
if (i % 2 == 0)
continue; // 跳过偶数
std::cout << i << std::endl;
}
NOTE
避免滥用 break
和 continue
:虽然 break
和 continue
是非常实用的控制流工具,但通常只在少数部分为了简化代码出现,过度使用它们会让代码变得难以理解(并且这种需求通常可以选择其他控制流语句完成
1.6 类简介
类是 C++ 支持面向对象编程的核心概念。通过类,程序员可以将数据与操作这些数据的方法打包在一起,从而实现更高层次的抽象和代码复用,很多标准库容器就是系统自带的类,C++ 还允许开发者创建和这些内置类型一样方便易用的类类型。
什么是类
- 类是 C++ 中的一种用户自定义类型,它可以封装数据成员(通常是变量)和成员函数(也称为方法
) 。 - 对象是类的实例,通过类创建对象 **,就像通过数据类型创建变量一样。
类允许程序员将数据和相关操作结合在一起,实现信息隐藏和模块化设计。
class Sales_item {
public:
double avg_price() const;
// 成员函数声明
private:
std::string isbn; // 数据成员:书号
unsigned units_sold = 0; // 数据成员:销售数量
double revenue = 0.0; // 数据成员:收入
};
- public:对外公开的成员,类的用户可以直接访问。
- private:私有成员,外部用户无法直接访问,只能通过类的成员函数操作。
定义成员函数
在类的声明中,成员函数只是声明,可以在类外实现。
double Sales_item::avg_price() const {
return (units_sold == 0) ? 0 : revenue / units_sold;
}
Sales_item::
指明avg_price
是Sales_item
类的成员函数。const
表明函数不会修改成员变量的值。
NOTE
封装是面向对象编程的重要特性,封装允许类的设计者隐藏内部实现细节,用户只能通过类的接口与对象交互。这种方式有助于减少复杂性和避免意外错误。
使用类的对象
创建类的对象与创建内置类型的变量类似,使用类定义的对象可以调用其公有成员函数。