目录
1、何为常量
2、关键字
3、实型
4、水平制表符
5、string字符串
6、C++中的三目运算符
7、随机数种子
8、结构体
9、各的区
10、引用
11、函数默认参数
12、函数占位参数
13、函数重载
14、私有属性
15、让另一个类作为本类的成员
16、声明和实现的文件结构
17、构造和析构
18、拷贝构造函数
19、默认的构造函数
20、深浅拷贝
21、初始化列表
22、类对象成员
23、静态成员
24、成员变量&成员函数
25、this指针
26、空指针访问成员函数
27、const修饰成员函数
28、友元
29、运算符重载
1:加号运算符重载
2:左移运算符重载
3:递增运算符重载
4:赋值运算符重载
5:关系运算符重载
6:函数调用运算符重载
30、继承
31、多态
32、文件操作
33、模板
1:函数模板
2:类模板
34、STL
35、STL容器
1:vector容器
2:string容器
3:deque容器
4:例程1
5:stack容器
6:queue容器
7:list容器
8:set/multiset容器
9:map和multimap
10:例程3
36、STL函数对象
1:函数对象(仿函数)
2:谓词
3:内建函数对象(内建的仿函数)
37、STL常用算法
1:遍历算法
2:查找算法
3:排序算法
4:拷贝和替换算法
5:算数生成算法
6:集合算法
1、何为常量
- #define 定义的
- const 修饰的变量
2、关键字
- 在 C++ 中,
string
并不是一个关键字,而是std
命名空间中定义的一个类。
3、实型
小数在C++中不管是f还是d默认配置都是显示6位有效数字
4、水平制表符
- 8个空格
5、string字符串
- 在 C++ 中,
string
并不是一个关键字,而是std
命名空间中定义的一个类
- 用法1
6、C++中的三目运算符
- 返回的是变量值,可以继续赋值
7、随机数种子
8、结构体
C++中结构体变量的结构体关键字可以省略
9、各的区
- 代码区
- 全局区:全局变量、静态变量、常量(字符串常量、const修饰的变量(const修饰的全局变量(全局常量)));const修饰的局部变量(局部常量)不在全局区;
- 堆区
- 栈区
02 程序的内存模型-内存四区-全局区_哔哩哔哩_bilibili
10、引用
int a = 10; int b = 20; //int &c; //错误引用必须初始化 int &c = a; //一旦初始化后,就不能改变引用 c = b; //这里是赋值操作,不是更改引用
- 引用的本质在C++内部实现是一个指针常量
- 引用做函数参数
- 引用做函数返回值
- 不要返回局部变量引用
- 函数调用作为左值
- 常量引用
11、函数默认参数
- 设置函数的默认参数后在给函数传参时如果不给参数列表传参或者只传局部参数剩下参数的值就用默认参数替代;
- 函数某个位置已经有了默认参数,那么从这个位置往后,从左往右都必须有默认值;
- 函数声明有默认参数,则函数实现就不能有默认参数,反之也是;
12、函数占位参数
13、函数重载
- 满足重载条件
- 在同一个作用域下;
- 函数名称相同;
- 函数参数类型不同或个数不同或顺序不同;
- 函数返回值不可以作为函数重载的条件。
- 引用作为重载条件
- 函数重载碰到默认参数,下面这种如果func2(10);是错误的出现二意性;
14、私有属性
- 将所有成员属性设置为私有,可以自己控制读写权限(即通过是否提供读写方法来实现);
- 对于写权限,可以检测数据的有效性(即在对应方法中做检测 );
15、让另一个类作为本类的成员
- 在Cricle中把Point作为类成员
#include <iostream> #include <string> #include <ctime> #include <cmath> using namespace std; class Point { public: void setX(double x) { m_x = x; } void setY(double y) { m_y = y; } double getX() { return m_x; } double getY() { return m_y; } private: double m_x; double m_y; }; class Cricle { public: void setR(double r) { m_r = r; } double getR() { return m_r; } void setCenter(Point center) { m_p = center; } Point getCenter() { return m_p; } private: Point m_p; double m_r; }; void isInCricle(Point &p, Cricle &c) { double distance = sqrt(pow(c.getCenter().getX() - p.getX(),2) + pow(c.getCenter().getY() - p.getY(),2)); if (c.getR() == distance) { cout << "在圆上" << endl; } else if(c.getR() > distance) { cout << "在圆内" << endl; }else { cout << "在圆外" << endl; } } int main() { Cricle c; Point p; p.setX(10); p.setY(0); c.setCenter(p); c.setR(10); Point p1; p1.setX(10); p1.setY(10); isInCricle(p1,c); system("pause"); }
16、声明和实现的文件结构
17、构造和析构
- 构造函数可以有参数、没有返回值、可以发生重载:
- 有参构造函数;
- 无参构造函数:
- 即默认构造函数;
- 在调用默认函数时不要加(),如果加了编译器会认为是一个函数声明,不会认为是创建对象
- eg:Person p1(); 声明了一个函数p1,返回值为Person类参数为空;
- 普通构造函数;
- 拷贝构造函数
- const修饰以及引用
- 调用方法
- 括号法
- 显示法(匿名对象)
- 隐式转换法
- 析构函数不可以有参数、没有返回值、不可以重载;
18、拷贝构造函数
- 会调用拷贝构造函数的情况
- 使用一个已经创建完毕的对象来初始化一个新对象
- 以值传递的方式给函数参数传值
- 以值方式返回局部对象
19、默认的构造函数
- 默认构造函数,无参函数体为空;
- 默认析构函数,无参函数体为空;
- 默认拷贝构造函数,函数体对属性值进行拷贝;
- 除了默认构造函数外还会默认添加一个重载运算符operator对属性进行值拷贝;
- 用户定义了有参构造函数,C++不会再提供默认无参构造函数,会提供默认拷贝函数;
- 用户定义了拷贝构造函数,C++不会再提供其他构造函数;
20、深浅拷贝
- 浅拷贝:简单的赋值拷贝操作;(默认的拷贝构造函数就是浅拷贝)
- 问题点如果属性是new在堆区申请的,浅拷贝只是值拷贝,拷贝完的对象指向的是同一个地址同一块内存区域,只要通过其中一个对象改变这个值,另外一个对象对应的也被修改;
- 在析构中delete掉new,被浅拷贝的对象会释放一次后,原对象又会释放一次该内存,导致堆区内存被重复释放;
- 深拷贝:在堆区重新申请空间,进行拷贝操作;
- 如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题;
21、初始化列表
- 用来初始化属性
22、类对象成员
- C++类中的成员可以是另一个类的对象,称该成员为对象成员
- B类中有对象A作为成员,A为对象成员
- 构造:A先构造然后B再构造
- 析构:B先析构然后A再析构
23、静态成员
- 静态成员变量
- 所有对象共享一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化
- 可以通过类名直接访问
- 静态变量不属于某个对象,是所以对象共享的一份数据,所有可以通过对象访问也可以通过类名访问(前提为public,不为public也是共享一份数据)
- 静态成员函数
- 所有对象共享一个函数,即可以通过类名访问(前提为public,不为public也是共享一个函数)
- 静态成员函数只能访问静态成员变量
- 可以通过类名直接访问
24、成员变量&成员函数
- 类内的成员变量和成员函数分开存储
- 只有非静态成员变量占对象空间
- 非静态成员函数也不占对象空间(本质上只有一份,通过this指针来区分是哪个对象在调用)
- 静态成员变量、静态成员函数不占对象空间,不属于某一个对象
25、this指针
- 用途一,用this指针解决名称冲突
错
对
- 用途二用于实现链式操作
如果返回类型是值而不是引用那么返回的是创建一个新的临时对象而不是原来的对象
26、空指针访问成员函数
27、const修饰成员函数
- 常函数
- 成员函数加const后称为常函数
- 常函数内不可以修改成员属性,但能读
- 成员属性声明时加mutable关键词后就可以在常函数内修改
- 常对象
- 声明对象前加cons称为常对象
- 常对象只能调用常函数,因为普通函数是可以修改成员属性,而常对象是不允许修改成员属性
- 常对象不能修改成员属性,可以修改mutable关键词的属性
28、友元
- 为了让一个函数或者类访问一个类中的私有成员
- 全局函数做友元
- 类做友元
- 成员函数做友元
29、运算符重载
1:加号运算符重载
- 只对自定义数据类型对象可以重载,对于内置数据类型的表达式的运算符是不可改变
- 通过成员函数重载
- 通过全局函数重载
- 运算符也可以重载
2:左移运算符重载
- 可以输出自定义数据类型
- 一般只用全局函数重载<< 运算符
3:递增运算符重载
- this是指向对象的指针,要获得对象就要*this,解引用指针获得对象;
- 重载递增运算符(前置递增返回的是引用(可以实现连续递增),后置递增返回的是值(不能实现连续递增))
4:赋值运算符重载
- 需要赋值运算符重载的原因同浅 深拷贝
- 为什么要先释放内存,因为可能是字符串的赋值重载,那么重载字符串的长短是可能不相等的所以要删掉原来的
5:关系运算符重载
6:函数调用运算符重载
- ()也可以重载;
- 重载后是使用方式与函数调用很像,因此称为仿函数;
- 仿函数没有固定写法;
30、继承
- 语法: class 子类 :继承方式 父类
- 子类也称为派生类,父类称为基类
- 公共继承、保护继承、私有继承
- 从父类继承过来的成员,哪些属于子类对象中:非静态成员属性都会被子类继承下去;父类中的私有成员属性也会被继承,只是被编译器隐藏起来而访问不到;
- 继承中的构造和析构顺序
- 先有父类构造再子类构造
- 先子类解析再父类解析
- 同类对象成员
- 继承中同名成员处理方式
- 访问之类同名成员,直接访问即可
- 访问父类同名成员,需要加作用域
子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数,如果想访问到父类中被隐藏的同名成员函数需要加作用域
同名静态成员的继承
方式一通过对象访问
同非静态成员出现同名处理方法一致。
- 访问之类同名成员,直接访问即可
- 访问父类同名成员,需要加作用域
- 通过类名访问
- 多继承
- 多继承可能会引发父类中有同名成员出现,需要加作用域区分
- 棱形继承
- 两个派生类继承同一个基类
- 又有某个类同时继承这两个基类
- 解决办法:虚继承虚、虚基类,只有一份数据
31、多态
- 静态多态:
- 函数重载和运算符重载属于静态多态,复用函数名
- 静态多态的函数地址早绑定——在编译阶段确定函数地址
- 动态多态(重写)
- 派生类和虚函数实现运行时多态
- 动态多态的函数绑定的晚——运行阶段确定函数地址
- 动态多态的条件:有继承关系、子类重写父类的虚函数
- 且要通过父类的指针或引用来指向执行子类对象
父类的引用再指向子类对象,C++中允许父子之间的类型转换不需要强转
动态多态原理
父类有virtual就会有一个虚函数指针和对应的虚函数表记录虚函数的地址
多态例子1--计算器
纯虚函数和抽象类
子类必须重写抽象类中的纯虚函数,否则有属于抽象类,即也无法实例化这个子类
多态例子2--制作饮品
虚析构和纯虚析构
如果没有虚析构就不会调用子类的析构
不管是虚析构还是纯虚构都要有函数内容体,因为父类也可能也在堆中的属性,这时就需要用析构来释放;纯虚析构的实现
多态例子3--组装电脑
32、文件操作
- 文本文件
- 二进制文件
33、模板
1:函数模板
- 如交换两个数据,数据类型各式各样,但交换的方式是基本一致的,方法是一样的只是数据类型不一样,将类型参数化
- 模板的使用方法有自动类型推导法、显示指定类型
- 自动类型推导,必须推导出一致的数据类型T才可以使用
- 模板必须要确定出T的数据类型,即使函数没有参数也要明确一个T的数据类型否则报错没有函数参数时任意申明一个就可以,才可以使用,
- 函数模板案例-数组排序
- 函数模板与普通函数的区别
- 普通函数与函数模板的调用规则
- 如果函数模板和普通函数都可以调用,优先调用普通函数
- 可以通过空模板参数列表来强制调用函数模板
- 函数模板也可以发生重载
- 如果函数模板可以更好的匹配,优先调用函数模板(这里会调用myPrint(T a,T b),因为调用myPrint(int a,int b)要进行隐式转换,而直接调用前者可以更好的匹配)
- 模板局限性
2:类模板
- 尖括号又叫模板的参数列表
- 类模板与函数模板区别
- 类模板没有自动类型推导的使用方法,只能显示指定类型
- 类模板在模板参数列表中可以有默认参数二个参数列表默认为int,在使用的时候可以不写如果没有写就默认为int)
- 类模板中的成员函数创建时机
- 普通类中的成员函数一开始就可以建立
- 类模板中的成员函数在调用时才会创建
- 类模板对象做函数参数
- 类模板实例化出来的对象,向函数传参的方式
- 指定传入的类型(直接显示对象的数据类型,告诉传的是什么样的类模板对象)
- 参数模板化(将对象中的参数变为模板进行传递,将类模板的参数再变为模板)
- 整个类模板化(将这个对象类型模板化进行传递)
- 类模板与继承
- 当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
- 如果不指定编译器无非给子类分配内存
- 如果想灵活指定出父类中T的类型,之类也需变成模板
- 类模板成员函数类外实现
- 类内实现
- 类外实现
- 类模板分文件编写
- 类模板成员函数创建时机是在调用阶段,导致分文件编写时链接不到解决办法
- 1:直接包含.cpp源文件
- 2:将声明和实现写在同一个文件中,并更改后缀名为.hpp;
- 类模板与友元
- 类模板配合友元函数的类内和类外实现
- 全局函数类内实现-直接在类内声明友元即可
- 全局函数类外实现-需要提前让编译器知道全局函数的存在
- 案例可以存储内置数据和自定义数据类型的数组
34、STL
- STL广义上分为:容器、算法、迭代器(算法通过迭代器来访问容器)
- 容器和算法之间通过迭代器进行无缝连接
- STL六大组件:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器
35、STL容器
1:vector容器
- vector的构造函数
- vector的赋值
- vector容量和大小
- vector插入与删除
- vector数据存取
- vector互换容器
- vector预留空间
- STL中最常用的容器为vector,可以理解为数组
- 存放内置数据类型
- 存放自定义数据类型
- Vector容器嵌套容器
2:string容器
- string的构造函数
- string赋值操作
- string字符串拼接
- string查找和替换
- string字符串比较
- string字符存取
- string插入和删除
- string子串
3:deque容器
- deque容器的构造函数
- deque赋值操作
- deque容器大小设置
- deque容器的插入删除
- deque容器的数据存取
- deque容器的排序
4:例程1
5:stack容器
- stack接口
6:queue容器
- queue接口
7:list容器
- list构造函数
- list赋值与交换
- list容器大小操作
- list插入与删除
- list数据存取
- list的反转和排序
- 案例
8:set/multiset容器
- set构造和赋值
- set大小和交换
- set插入与删除
- set查找与统计
- set与multise区别
- pair对组
- set容器排序
- 存放内置数据类型的自定义排序
- 存放自定义数据类型的自定义排序
9:map和multimap
- map构造和赋值
- map大小和交换
- map插入与删除
- map查找与统计
- map排序
10:例程3
36、STL函数对象
1:函数对象(仿函数)
2:谓词
GreateFive创建了一个匿名对象然后再调用这个匿名对象的()函数重载符
3:内建函数对象(内建的仿函数)
- 算数仿函数
- 关系仿函数
- 逻辑仿函数
37、STL常用算法
1:遍历算法
- for_each
- transfrom
2:查找算法
- find
- find_if
- adjacent_find
- binary_search(有序:按升序或者降序或者其他进行排序)
- count
- count_if
3:排序算法
- sort
- random_shuffle
- merge
- reverse
4:拷贝和替换算法
- copy
- replace
- replace_if
- swap(互换的两个容器要相同)
5:算数生成算法
- accumulate
- fill
6:集合算法
- set_intersection
- set_union
- set_difference
Data: 24.4.15-5.15