文章目录
C++基础
文章目录 |
---|
《C++ Primer Plus》 |
一、入门学习路线图
大致是这样,我有的时候学了很多语言,一个语言写习惯了再扭回来就会发现全忘记了,这个图也是为了帮助我进行回忆
二、基础语法
2.1 基本数据类型
表格选自《菜鸟教程》
类型 | 描述 |
---|---|
bool | 存储值 true 或 false。 |
char | 通常是一个字符(八位)。这是一个整数类型。 |
int | 对机器而言,整数的最自然的大小。 |
float | 单精度浮点值。单精度是这样的格式,1位符号,8位指数,23位小数。![]() |
double | 双精度浮点值。双精度是1位符号,11位指数,52位小数。![]() |
void | 表示类型的缺失。 |
wchar_t | 宽字符类型。 |
内置整型
- long
- int
- short
- char
- bool
- long long
内置浮点型
- float
- double
- long double
无符号版本:在数据类型前加unsigned
两者的区别在于,有符号版本的数据包含负数,但是囊括的范围不同,例如
- 有符号:-32768 —— +32767
- 无符号:0 —— 65535
常量限定
- const:就像我们Java用的final一样,一般是给常量用的(不需要修改的数据)
2.2 运算符
算数运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | -3 | -3 |
+ | 加 | 10+5 | 15 |
- | 减 | 10-5 | 5 |
* | 乘 | 10*5 | 50 |
/ | 除 | 10/5 | 2 |
% | 取模 | 10%3 | 1 |
++ | 前置递增 | a=2;b=++a; | a=3;b=3; |
++ | 后置递增 | a=2;b=a++; | a=3;b=2; |
– | 前置递减 | a=2;b=–a; | a=1;b=1; |
– | 后置递减 | a=2;b=a–; | a=1;b=2; |
赋值运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
= | 赋值 | a=2;b=3; | a=2;b=3; |
+= | 加等于 | a=0;a+=2; | a=2; |
-= | 减等于 | a=5;a-=3; | a=2; |
*= | 乘等于 | a=2;a*=2; | a=4; |
/= | 除等于 | a=4;a/=2; | a=2; |
%= | 模等于 | a=3;a%=2; | a=1; |
比较运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
== | 相等于 | 4 == 3 | 0 |
!= | 不等于 | 4 != 3 | 1 |
< | 小于 | 4 < 3 | 0 |
> | 大于 | 4 > 3 | 1 |
<= | 小于等于 | 4 <= 3 | 0 |
>= | 大于等于 | 4 >= 1 | 1 |
逻辑运算符
运算符 | 术语 | 示例 | 结果 |
---|---|---|---|
! | 非 | !a | 如果a为假,则a为真;如果a为真,则a为假。 |
&& | 与 | a & & b | 如果a和b都是真,则结果为真,否则为假。 |
ll | 或 | a l l b | 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。 |
三目运算符
c = (a>b ? a:b);
如果a大于b,a的值给c,反之则b的值给c
2.3 逻辑循环语句
if
int a = 0;
std::cout << "初始值 a = " << a << "\n";
std::cout << "请输入 a 的新值 = ";
std::cin >> a;
if (a >= 10 && a < 20 )
{
std::cout << "A 的值 大于等于10小于20";
}
else if (a >= 20 && a < 30)
{
std::cout << "A 的值 大于等于20小于30";
}
else
{
std::cout << "A的值不在10-30的范围区间";
}
while
while (a<5)
{
std::cout << "输出a = " << a << "\n";
a++;
}
do while
// 区别:会先执行一次循环语句,再判断循环条件
int num = 0;
do
{
std::cout << num << "\n";
num++;
} while (num < 10);
for
for (int a = 0 ; a < 10 ; a++)
{
std::cout << a << "\n";
}
switch
int main()
{
int x = 2;
switch (x)
{
case 1:
cout << "输出1" << endl;
break;
case 2:
cout << "输出2" << endl;
break;
case 3:
cout << "输出3" << endl;
break;
default:
cout << "未命中" << endl;
break;
}
return 0;
}
跳转语句
break ;
// 用于跳出循环
continue ;
// 跳过本次循环,执行下一次循环
goto ;
// 用来跳转到标记位置
2.4 复合数据类型
数组
放在一个连续的内存中,数组中的每个元素都是相同的数据类型
int a[] = {1,2,3,4,5};
for (int i = 0; i < 5; i++)
{
std::cout << a[i] << "\n";
}
二维数组
// 数据类型 数组名【行数】【列数】
int a[2][3];
int a[2][3] =
{
{1,2,3},
{4,5,6}
};
std::cout << a[0][1];
字符串
C++处理字符串的方式有两种
-
来自C语言风格的字符串,可以说是char数组
-
String类库
string a; a = "hello"; cout << a << endl;
get与getline
// 每次读取一个字节
char x;
cin.get(x);
// 读取一行
// 第二个参数表示要读取的字符数,多出来的空间会存储自动在结尾处添加的空字符
char y[2];
cin.getline(y, 10);
2.5 指针/引用
什么是值传递?什么是地址传递?
值传递:形参无法改变实参,例如函数中的形参传递
地址传递:传递时通过指针将信息地址进行传递,对这个信息改变的时候,相当于是对其内存地址的操作,所以实参会被改变
基本用法
int main()
{
// 定义普通int类型数据
int a = 10;
// 指针定义的语法:数据类型 * 指针变量名;
int* p;
// 让指针记录变量a的地址
// &a:表示属性a的内存地址
p = &a;
cout << "a的地址为: " << &a << endl;
cout << "指针p为: " << p << endl;;
cout << "指针p的值为: " << *p << endl;;
return 0;
}
指针的另外几种分类
-
空指针 - 指向的内存地址为NULL
-
野指针 - 指针变量指向非法的内存空间,例如指向的这个空间没人用,没有被定义,所以是非法的
-
修饰指针
- 常量指针(可以更改指针的指向,不能更改指针指向的值)
- 指针常量(不可以更改指针的指向,能更改指针指向的值)
- 双重修饰(上面两个都不能改)
int a = 10 ; int b = 20 ; const int * const p = &a // 常量 指针 常量
this指针
- this指针是隐含每一个非静态成员函数内的一种指针
- this指针不需要定义,直接使用即可
- 当形参和成员变量同名时,可用this指针来区分
- 在类的非静态成员函数中返回对象本身,可使用return *this
#include <iostream>
using namespace std;
class MyClass
{
int age;
public:
int res(int age) {
this->age = age + 1;
return this->age;
}
};
int main()
{
MyClass p1{};
int xx = p1.res(3);
cout << xx << endl;
}
引用
相当于一个软连接一样,但是如果改了b的值,a的值也会随之改变
- 引用必须初始化
- 引用一旦初始化后,值就不可更改
- 引用的本质就是指针常量
int a = 10;
int &b = a;
2.6 函数
函数默认值
在C++中,函数的形参列表中的形参是可以有默认值的
// 语法: 返回值类型 函数名 (参数 = 默认值){ }
int func(int a ,int b = 20,int c = 30)
{
return a + b + c ;
}
// 如果函数声明有默认参数,函数实现就不能有默认参数
// 如果某个位置已经有了默认参数,函数实现就不能有默认参数
占位参数
// C++中,函数的形参列表丽可以有占位参数,用来做占位,调用函数时必须填补该位置
// 语法: 返回值类型 函数名 (数据类型){}
void test01(int a,int)
{
cout << "this is a XXX" << endl;
}
函数重载
作用:函数名可以相同,提高复用性
重载条件
- 同一个作用域下
- 函数名称相同
- 函数参数类型不同,或者个数不同,或者顺序不同
2.7 日期/时间
1
三、面向对象
封装、继承、多态
struct与class的区别:struct默认是公有权限,class默认是私有权限
3.1 strust - 结构体
就是用户自定义的数据类型,允许用户存储不同的数据类型
#include <iostream>
using namespace std;
// 定义结构体一
struct Student {
string name;
unsigned int age;
};
// 定义结构体二:typedef取别名
typedef struct Student02 {
string name;
unsigned int age;
}CoolMan;
// 普通结构体玩法
void s01() {
Student s1 = { "test01",18 };
cout << s1.name << endl;
cout << s1.age << endl;
cout << "普通结构体玩法" << endl;
};
// 结构体数组
void s02() {
Student s2[] = {
{"test01",17},
{"test02",13}
};
// 省略for循环代码...
}
// 结构体指针
void s03() {
Student s3[] = {
{"test01",17},
{"test02",13}
};
Student* ss3 = &s3[0];
};
int main()
{
Student02 CoolMan;
return 0;
}
3.2 union - 共用体
一种数据类型,可以存不同的数据类型在里面,但是任何时候只能有一个成员带有值,C里面的,我不想学了
3.3 enum - 枚举
枚举是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读
#include <iostream>
using namespace std;
// 枚举的定义
enum Color
{
red = 'red',
blue = 'blue',
green
};
// 或者直接省略名字
enum
{
Mon = 1,
Tur = 2,
Wen
}day;
int main()
{
day = Mon;
cout << "输出day的结果:" << day << endl;
Color co01 = red;
cout << "输出color的结果:" << co01 << endl;
// 这里输出了一串数字
// 因为枚举是被当做 int 或者 unsigned int 类型来处理的
return 0;
}
3.4 class - 类
首先看看基本语法
- public - 公共权限 - 类内可以访问,类外可以访问
- protected - 保护权限 - 类内可以访问,类外不可以访问
- private - 私有权限 - 类内可以访问,类外不可以访问
#include <iostream>
using namespace std;
// 类的结构
class MyClass
{
public:
// 公有权限
MyClass();
~MyClass();
private:
// 私有权限
protected:
// 保护权限
};
MyClass::MyClass()
{
// 构造函数
cout << "实例创建时出现" << endl;
}
MyClass::~MyClass()
{
// 析构函数
cout << "实例被销毁时出现" << endl;
}
int main()
{
MyClass m1;
return 0;
}
封装
核心思想:对扩展开放,对修改关闭 —— 属性放在私有权限,在公共权限中写get和set方法
#include <iostream>
using namespace std;
class Adder{
public:
// 构造函数
Adder(int i = 0)
{
total = i;
}
// 对外的接口
void addNum(int number)
{
total += number;
}
// 对外的接口
int getTotal()
{
return total;
};
private:
// 对外隐藏的数据
int total;
};
int main( )
{
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
cout << "Total " << a.getTotal() <<endl;
return 0;
}
继承
基本语法
// 基类
class Animal {
// eat() 函数
// sleep() 函数
};
//派生类
class Dog : public Animal {
// bark() 函数
};
多继承 or 菱形继承
# 多继承 —— 开发中不建议
语法:class 子类 : 继承方式 父类1, 继承方式 父类2....
# 菱形继承 —— 为解决资源浪费
语法:class XX2: virtual public XX1 {} ;
继承权限问题
- 公有继承:不改变基类成员的访问权限
- 私有继承:基类所有成员在子类中的访问权限变为private
- 保护继承:基类中public成员变为子类的protected成员,其它成员的访问
权限不变
基类中的 private 成员不受继承方式的影响,子类永远无权访问
多态
"一个接口,多种实现"
分为两类
-
静态多态
函数重载 和 运算符重载 属于静态多态,复用函数名
-
动态多态
派生类 和 虚函数 实现运行时多态
两者的区别在于
- 静态多态的函数地址早绑定,
编译阶段
确定函数内存地址 - 动态多态的函数地址晚绑定,
运行阶段
确定函数内存地址
3.5 友元
1
四、STL模板库
1