1.1 C++基础知识
C++语言是C语言的超集,主要被设计为面向对象的C,常称为包含类的C。但两者并不相同,如果是C语言程序员,请关注新的或不熟悉的语法。
1.1.1 小程序Helloworld
最简单的入门C++程序:
//helloworld.cpp
#include <iostream>
int main()
{
std::cout << "Hello,world!" << std::endl;
return 0;
}
这里涉及的概念有:
- 注释
- 预处理指令
- main函数
- 输入输出流
1)注释
供编程人员(自己或后来)理解代码内容
单行注释用 //
多行注释用/* 注释内容*/
2)预处理指令
生成一个C++程序共有3个步骤。首先,代码在预处理器中运行,预处理器会识别代码中的元信息(meta-information)。其次,代码被编译或转换为计算机可识别的目标文件。最后,独立的目标文件被链接成一个可执行程序。
预处理指令以#字符开始,前面示例中的#include<iostream>就是如此。在此例子中,include指令告诉预处理器:提取<iostream>头文件中的所有内容并提供给当前文件。头文件最常见的用途是声明在其他地方定义的函数。函数声明会通知编译器如何调用这个函数,并声明函数中参数的个数和类型,以及函数的返回类型。而函数定义包含了这个函数的实际代码。在C++中,声明通常放在扩展名为.h的文件中,称为头文件,其定义通常包含在扩展名为.cpp的文件中,称为源文件。
iotream头文件声明了C++提供的输入输出机制。如果程序没有包含这个头文件,甚至无法执行其仅需要完成的输出文本任务。
注意:
在C中,标准头文件的名称通常以.h结尾,如<stdio.h>,不使用名称空间。
在C++中, 标准库头文件的名称省略了.h后缀,如<iostream>;所有文件都在std名称空间和std的子名称空间中定义。
C中的标准库头文件在C++中有新旧两个版本:
- 不使用.h后缀,改用前缀c;这是新版本,一切放在std名空间中,如<cstdio>;
- 使用.h后缀,这是旧版本。这些版本不使用名称空间,如<stdio.h>。
最常用的预处理指令如下
预处理指令 | 功能 |
#include【file】 | 包含头文件,将内容插入指令所在位置 |
#define 【key】【value】 | 每个指定的key都被替换为指定的值 |
#ifdef 【key】 #endif #ifndef 【key】 #endif | 用于代码是否包含与丢弃 |
#pragma 【xyz】 | 通常会显示一条警告或错误信息。 |
避免重复包含的预处理指令例子:
#ifndef MYHEADER_H
#define MYHEADER_H
//这里填入头文件内容
#endif
或者,如果编译器支持#pragma once指令
#pragma once
//这里是头文件内容
3)main函数
main()函数是程序的入口。main()函数返回一个int值以指示程序的最终执行状态。在main()函数中或者没有参数,或者具有两个参数,如下所示:
int main(int argc, char* argv[])
argc给出了传递给程序的实参个数,argv给出了这些实参。注意argv[0]可能是程序的名称也可能是空字符串,但不依赖它。实际参数从索引1开始。
4)输入输出流
std::cout << "There are " << 219 << " ways I love you." << std::endl;
std::cout 是对应于用户控制台或标准输出的滑槽,此外,还有用于输出错误信息的std::cerr.
std::endl 代表序列的结尾。当输出流遇到std::endl时就会输出所有内容,并转移到下一行。
常见转义符:
\n 换行
\r 回车
\t 制表符
\\ 反斜杠字符
\" 引号
1.1.2 名称空间
名称空间用来处理不同代码段之间名称冲突问题。例如,你编写了一段代码,其中有一个名为foo()的函数。某天,使用第三方库,其中也有一个foo()函数。编译器无法判断代码究竟要使用哪个版本的foo()(你写的foo还是库中有的foo函数?)。库函数的名称无法改变,而改变自己的函数又会感到非常痛苦。这种情况下可以使用名称空间。
//namespaces.h
namespace mycode {
void foo();
}
//namespace.cpp
#include <iostream>
#include <namespace.h>
void mycode::foo()
{
std::cout << "foo() called in the mycode namespace" << std::endl;
}
或者
#include <iostream>
#include "namespaces.h"
namespace mycode {
void foo()
{
std::cout << "foo() called in the mycode namespace " << std::endl;
}
}
如果嫌每次都加上名空间前缀比较麻烦,可以在文件头部加上using语句,例子如下,
#include "namespaces.h"
using namespace mycode;
int main()
{
foo();
return 0;
}
使用using指令重新编写hello world程序,如下所示:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, World!" << endl;
return 0;
}
还可以使用using指令来引用名称空间内的特定项。例如,只想使用std名称空间中的cout。可以这样引用:
using std::cout;
cout << "hello,world!" << std::endl;
警告:
切勿在头文件中使用using指令或using声明,否则添加你的头文件的每个人都必须使用它。
C++17允许方便的使用嵌套的名称空间,即将一个名称空间放在另一个名称空间中。
namespace MyLibraries::Networking::FTP {
//实现代码
}
还可以使用名称空间别名,为另一个名称空间指定一个简短的新名称,如:
namespace MyFTP = MyLibraries::Networking::FTP;
1.1.3 字面量
字面量用于在代码中编写数字或字符串。C++支持大量标准字面量。如指定数字(123):
- 十进制字面量123
- 八进制字面量0173
- 十六进制字面量0x7B
- 二进制字面量0b1111011
C++中的其他字面量示例包括:
- 浮点数,如3.14f
- 双精度浮点数,如3.14
- 单个字符,如‘a’
- 以零结尾的字符数组,如“character array”
1.1.4变量
在C++中,可以在任何位置声明变量,并且在声明一个变量所在行的任意位置使用该变量。
注意:
当代码中使用了未初始化的变量时,多数编译器会给出告警信息或报错信息。当访问未初始化的变量时,某些C++环境可能会报告运行时错误。
C++没有提供基本的字符串类型。但是作为标准库的一部分提供了字符串的标准实现。
可使用类型转换方式将变量转换为其他类型。例如,可将float转换为int。
float myFloat = 3.14f;
int i1 = (int) myFloat; //方法1:老式C风格
int i2 = int(myFloat); //方法2:很少使用
int i3 = static_cast<int> (myFloat); //方法3,:推荐使用
1.1.5 运算符
在C++中,运算符可以是二元的,一元的甚至是三元的。在C++中只有一个条件运算符。
运算符 | 说明 | 用法 |
= | 二元赋值运算 | int i=3; |
! | 一元非运算 | bool b= !true; |
+ | 二元加法 | int i= 3+ 2; |
- * / | 减法 乘法 除法 | int i= 5 -1; int j= 5*2; int k = j/i; |
% | 模运算 | int rem= 5%2; |
++ | 自加,变量增1 | i++; ++i; |
-- | 自减,变量减1 | i--; --i; |
+= | i=i+j; 的简写 | i += j; |
-= *= /= %= | i=i-j; 的简写 i=i*j; 的简写 i=i/j; 的简写 i=i%j; 的简写 | i -= j; i *= j; i /= j; i %= j; |
& &= | 与 | i=j & k; j &= k; |
| |= | 或 | i = j| k; j |= k; |
<< >> <<= >>= | 移位 | i = i<< 1; i= i >> 1; i << = 1; i >>= 4; |
^ ^= | 异或 | i = i ^ j; i ^= j; |
1.1.6 类型
1)枚举类型
2)强枚举类型
3)结构体
1.1.7 条件语句
1.1.8 逻辑比较运算符
1.1.9 函数
1.1.10 C风格的数组
1.1.11 std::array
1.1.12 std::vector
1.1.13 结构化绑定
1.1.14 循环
1.1.15 初始化列表
1.1.16 其他
1.2 深入研究C++
1.2.1 C++中的字符串
1.2.2 指针和动态内存
1.2.3 const 的多种用法
1.2.4 引用
1.2.5 异常
1.2.6 类型推断
1.3 面向对象的C++
1.3.1 定义类
1.3.2 使用类
1.4 统一初始化
1.5 标准库
1.6 第一个有用的C++程序
1.6.1 雇员记录系统
1.6.2 Employee类
1.6.3 Database类
1.6.4 用户界面
1.6.5 评估程序
1.7 本章小结