// C++向下兼容C 与C重复内容不再记录 #include using namespace std;
int main() { //// 关于命名空间 namespace // 使用的using namespace std;目的是对std的命名空间进行缩写以便于后续编程 // 如: 使用后cout « … « endl; 使用前std::cout « … « endl;
//// 常量
//// 宏常量(静默化不可被修改,一般写在主函数外)
// #define 常量名 常量值
//// const修饰(对一个变量修饰为常量)
// 如: const int a = 10; ---> a为常量
//// 数据类型
//// 字符串
// string a = "内容"; -->存在字符串类型,包含在<string>头文件中
//// 布尔
// bool a = false, bool b = true;
//// auto (自动判断数据类型)
// 如: auto a = 7; --->表示a为int类型
// 有便于迭代器遍历时省去卬杂的声明
//// 运算符
//// %(取余)
// C++中小数不能进行取余运算
//// 三目运算符(C++中三目运算符返回的可以是变量)
// (a > b ? a : b) = 100;
// 结果是将100赋值给a或者b
//// for() -循环新用法
// for(int i : 数组a)
// {
// cout << a[i] << endl;
// } -->用于遍历数组(在该情况下i为传导值不可被更改,若想更改,用&变为引用变量)
//// 函数
// 函数内进行值传递时,并不会改变外界的数值(如想改变用指针)
// |
// ↓
// 解决方法请查找"引用"单元
//// 分文件书写
// 步骤1.创建.h后缀头文件
// 2.创建.cpp后缀源文件
// 3.在头文件中写函数申明
// 4.在源文件中写函数定义
//// 引用(符号&)
// 请与C中的和号&区分,C++中的引号是用来改变变量为引用变量
// 对于函数单元值不能改变的问题可以这样写: int formular(int &a)
// {
// a = 99;
// }
// 那么a的值就变为了99,若不是引用变量则a的值仍为输入时的值
//// 头文件
// C中的头文件大多可以用于C++
// 如: C: <stdio.h> C++: <cstdio>
// c: <math.h> C++: <cmath> ---> printf,scanf的运行效率比cin,cout高哟!
//// 容器(如vector,stack,queue,map,set都是容器)
// 都可以用.size()获取容器的大小
//// 关键词
//---------------------------------------------------<iostream>
//// cout用于输出变量
// cout << 内容1 << 内容2 << .... << endl;
//// cin用于输入键盘扫描值
// cin >> 赋值给的变量;
//---------------------------------------------------<string>
//// 可以使用string数据类型
//// getline(cin,将要录入的字符串);
// 用于读取一整行的字符串
//// 字符串变量.length
// 用于获取字符串的长度(不包含终止符)
// return 长度
//// 字符串变量.substr(启始索引,截取的长度)
// 用于截断字符串并返回截断出的字符串
//// to.string(将要转换的内容) -将别的类型转换为字符串
// 返回字符串
//// 将字符串转换为别的类型
//// stoi("一行字符串") 返回int
//// stof("一行字符串") 返回float
//// stolf("一行字符串") 返回long float
//// stol("一行字符串") 返回long
//// stoll("一行字符串") 返回long long
//// stoul("一行字符串") 返回unsigned long
//// stoull("一行字符串") 返回unsigned long long
//// printf输出字符串方法
// 如: printf("%s\n", s1.c_str());
//---------------------------------------------------<vector> / namespace std
//// vector --->(动态数组/矢量)
// 字面意思没有长度限制的数组
// 语法: vector<int> v1(数组大小,初始化数值); ---> 定义一个矢量整型数组v1(默认初始化,且初始化为0)
//// v1.resize(设置的数组长度);
// 默认设置后初始化为0
//// v1.begin() -->数组初始位置的指针
//// v1.end() -->数组结尾位置的指针(并非最后一个数,而是最后一个数的终止符' ')
//---------------------------------------------------<set> / namespace std
//// set --->(集合)
// ⼀个set 里面的各元素是各不相同的,而且set会按照元素进行从小到大排序
// 语法: set<int> a1;
//// a1.insert(数值) --->向集合中插入一个数值
//// a1.find(数值) --->查找集合中的数值,return索引指针
//// a1.erase(数值) --->删除集合中的数值
//---------------------------------------------------<map> / namespace std
//// map --->(键值对) 类比key
// 语法: map<键的数据类型,值的数据类型> b1;
// 如:b1["Hello"] = 5; --->将"Hello"的对应值设置为5
// cout << m["Hello"] << endl; --->访问map中"Hello"的值,若查询的键不存在则返回0;
//// b1.begin()->first (返回b1第一个元素的键)
//// b1.begin()->second (返回b1第一个元素的值)
//// b1.find(key) (找到对应的key如找到返回位置,未找到返回b1.end())
//---------------------------------------------------<stack> / namespace std
//// stack --->(栈)
// 语法: stack<int> c1;
//// c1.push(值) --->将值推入栈中
//// c1.top() --->访问栈顶元素
//// c1.pop() --->移除栈顶元素
//---------------------------------------------------<queue> / namespace std
//// queue --->(队列)
// 语法: queue<int> d1;
//// d1.push(值) --->将值推入队列中
//// d1.front() --->访问队列首元素的值
//// d1.back() --->访问队列尾元素的值
//// d1.pop() --->移除队列首元素
//---------------------------------------------------<unordered_map> / namespace std
//---------------------------------------------------<unordered_set> / namespace std
//// 区别:
// 和map(set) 相同只是省去了排序(从小到大)的步骤
//---------------------------------------------------<bitset>
//// bitset --->(用于处理二进制数)
// bitset<二进制位数> e1; --->e1全部初始化为0
// bitset<二进制位数> e1(1); --->将1转化为二进制数并赋值给e1
// bitset<二进制位数> e1("1010"); --->将前四位赋值为1010,如:0001010并赋值给e1
// bitset<二进制位数> e1(s,start,length); --->s字符串从start开始长度为length,并进行上述程序
//// bitset 相当于一个数组如果直接输出这是正常顺序,用数组形式输出则为反向
// 如 bitset<5> a; (a == 00010)
// cout >> a >> endl; (结果为: 00010)
// for(int i = 0; i < 5; i++)
// {
// cout >> a[i];
// } (结果为01000,倒序)
//// e1.any(); --->判断e1中是否有1
//// e1.none(); --->判断e1中是否不存在1
//// e1.count(); --->计数e1中1的个数
//// e1.test(索引); --->测试e1中下标处对应值是否为1
//// e1.set(索引); --->将e1中下标处对应值设置为1
//// e1.reset(); --->所有位归零
//// e1.reset(索引); --->将e1中下标对应值归零
//// e1.flip(); --->所有位取反
//// e1.to_ulong(); --->e1转换为unsigned long 类型
//---------------------------------------------------<algorithm>
//// sort(启始索引,尾部索引,排列模式) --->对一个数组或是容器进行排序
// 关于排列模式: sort()默认是升序排列 及 a < b
// ------将bool cmp()返回值变为 a > b后则为降序排列
// 排列模式逻辑: 返回为true时不进行互换 为false时则进行互换
// sort()遵循分区逻辑: 即先选定一个标准值然后依据该值对其余数据进行比较大的在后面,小的在前面,随后进行遍历排序完成排序
//// next_permutation(数组起始指针,数组末尾指针的下一位) -用来对升序数组进行,全排序遍历
//// reverse(数组的起始位置,末位置) --将数组中的数据反转
//---------------------------------------------------<iomanip>
//// << fixed << setprecision(2) ->用于对小数点后保留位数
// 如: cout << fixed << setprecision(2) << a << endl;(对a保留两位小数)
//// 迭代器 -便于在不同容器中遍历/迭代
// 类格式: for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it)
// auto简化后: for (auto it = vec.begin(); it != vec.end(); ++it)
// for简化后: for (const auto& it : vec)
//// 迭代器类别:
// 普通迭代器 (iterator) -->内部迭代常量,可修改
// 常量迭代器 (const_iterator) -->静默化内部迭代常量,不可修改
// 反向迭代器 (reverse_iterator) -->反向迭代
// const迭代器 -->对迭代器本身静默化,使迭代器指向一个固定的位置,但是该位置的值可以修改
//// Dev-Cpp 中使用C++11特性的方法
// 在菜单栏中⼯具-编译选项-编译器-编译时加⼊-std=c++11这句命令即可
//// 技巧性知识
//// 对于数组90°顺时针旋转坐标分析 原坐标(i,j) 数组总大小为y,x
// 则旋转后的坐标为(y - 1 - j,i)
////数组循环迭代输出的方法 -三次反转法
// 1.先整个反转
// 2.再前半段反转(长度为向右移动的距离)
// 3.后边段反转
////类与对象
/// 类: 三大特性: 1.封装 2.继承 3.多态
// 封装(将属性和行为作为一个整体):
// 语法: class 类名 { 访问权限 : 属性 / 行为};
// 访问权限: 1.public 公共权限 2.private 私有权限 3.protected 保护权限
// public: 类内可以访问 类外可以访问 子类可以访问父类中公共的内容
// protected: 类内可以访问 类外不可以访问 子类可以访问父类中保护的内容
// private: 类内可以访问 类外不可以访问 子类不可以访问父类中私有的内容
// *未申明权限类型时默认为私有权限
//
// 属性: 类所具有的属性,以mc为例苦力怕这个群体有自己的血量等各个数值
// 行为: 通常用函数代表,以mc为例苦力怕这个群体有自己的寻路机制,爆炸的动作
//
// 构造函数: 在创建对象时默认执行的函数用于对属性初始化赋值
// 语法: 类名(可以有参数,包括普通数据以及类){} ->(此处类名指创建对象时的类名)
// 析构函数: 在删除对象时默认执行的函数用于对属性进行删除前的处理
// 语法: ~类名(不能有参数){}
// ↑
// 注两函数要在公共部分有效
//
// 初始化列表: (可在创建对象时初始化成员)
// 语法: 类名(输入变量1,输入变量2.....) : 成员名1(变量1) , 成员名2(变量2) .... {}
//
// 静态成员: (static前缀,所有对象共享同一个变量/函数) *类内定义的静态变量需要在类外初始化
// *静态成员函数只能调用静态成员变量
//
// 常量成员: (const修饰) *常对象只能调用常函数
// *常函数不可修改成员属性(成员属性加上mutable 后便可修改)
// ↓
// 常函数定义: 返回类型 函数名() const {};
// *此处cosnt 相当于对this指针所指向的值修改为const
//
// this指针: this指针指向被调用的成员函数所属的对象(*this 可直接使用不用定义)
// *用法颇多可以探索(链式编程,避免函数名重复)
//
// 友元: 类似于函数声明,可以在定义类时对类外(函数/变量/类)加上 friend 前缀使该(函数/变量/类)能够调用类中的私密部分
//
// 运算符重载: 通过成员函数对运算符进行符号重载(+/-/*/'/'/<</==/</=/++/--/()....)效果类比string中s3 = s1 + s2,对+的新定义
// 方法: 在类中 返回数据类型 operator+(变量1,变量2....) {}
// operator-(变量1,变量2....) {}.....
// *如果想要定义左移运算符重载,只能在类外进行<<定义(还可以加上链式编程)
// *递增/减运算符重载,定义的区分方法 a++ -> void operator++(占位数据(如:int)) {}
// ++a -> void operator++() {}
// 继承(继承父类的基本属性):
// 子类定义语法: class 子类名 : 继承方式(例:public...) 继承父类名1 , 继承方式 继承父类名2 , ..... {};
// *继承后父类private属性不可访问(但是仍被继承)
// *继承下父子类中同名(变量/函数)可以通过作用域区分,例: son.a , son.father::a
// 继承方式: public 继承后的父类属性的权限模式不变
// protected 继承后的父类的属性权限都归为protected
// private 继承后的父类属性权限都归为private
// 虚继承: 在继承定义时加上前缀 virtual 继承方式 父类名 {}; 使得子类只继承一份父类 解决菱形继承问题
// |
// 菱形继承: 一个子类继承了两个父类(其父类继承了共同的父类,形状类似菱形) |
// *此时子类继承了两份跟父类,导致资源浪费,可使用虚继承来解决重复继承 ←+
// 多态(静态多态,动态多态):
// 静态多态: 函数重载,运算符重载,复用函数名
// 动态多态: 子类和虚函数在运行时多态(子类重写父类的虚函数,使得父类函数有多种形态 )
// *动态多态的使用,是调用父类引用或指针来执行子类的对象
//
// 纯虚函数: 语法: virtual 返回类型 函数名 (参数列表) = 0;
// 抽象类(无实例化对象): 当类中有了纯虚函数,这个类也称为抽象类
// *子类需重写父类虚函数,否则子类也为抽象类
//
// 虚析构函数: 将父类析构函数虚化,可以避免因多态调用导致子类内存泄漏问题
// 纯虚析构函数: 同纯虚函数的写法
// *需要在类外声明,否则报错
// *其所属类归为抽象类
/// 对象: 通过类创建的个体叫对象(理解为创建一个苦力怕这个个体,它具有苦力怕这个类的各种功能以及属性)
// 创建方式: 类名 对象名 (类似结构体)
// 访问: 对象名.访问属性/行为
// 对象赋值: 1.对象名(参数) 2.类名 对象名 = 类名(参数) 3.类名 对象名 = 参数
//
// 匿名对象: 类名(参数) 匿名对象在执行完当前行语句后立即释放(即执行析构函数)
//
// 拷贝: 1.深拷贝-通过申请内存进行拷贝(可能带来内存重复释放的问题)
// 2.浅拷贝-直接赋值拷贝
//
// 附属关系: 静态变量,非静态/静态函数不属于对象
// 而非静态变量属于对象
cout << "完结撒花" << endl;
}