0. 温习
0.1 虚继承
当咱们应用多继承的时候,子类的多个父类有同名成员,拜访的时候,会呈现二义性class CA{ public: int m_a;};class CB{ public:int m_a;};class CTest:public CA,public CB{};int main(){CTest obj;obj.m_a = 10;return 0;}
解决形式1:能够应用类的作用域拜访具体某一个父类的成员
解决形式2:给CA和CB形象出一个独特的父类,而后应用虚继承
class CBase{public: int m_a;};class CA:virtual public CBase{public: //int m_a;};class CB:virtual public CBase{public: //int m_a;};class CTest :public CA, public CB{};int main(){ CTest obj; obj.m_a = 20; obj.CA::m_a = 10; obj.CB::m_a = 20; return 0;}
如果类B虚继承自类A,此时类A就是虚基类
0.2 虚函数与多态
当咱们应用父类指针指向子类对象,调用虚函数,优先调用子类的虚函数。子类如果没有实现这个虚函数,就调用父类的。
虚函数是多态机制,属于动静联编。
virtual void fun() =0 ; 这个叫做纯虚函数。只是提供了接口,没有提供具体实现,实现由子类来实现。
抽象类:蕴含纯虚函数的类,也叫做抽象类。如果子类没有实现父类中的纯虚函数,子类也是抽象类。
抽象类的特点:不能定义对象
class Tuxing{public: virtual int ClacArea() = 0;};class Sanjiaoxing:public Tuxing{public: int ClacArea() { return m_nBottom * m_nHeight / 2; }private: int m_nBottom; int m_nHeight;};class CZhengfangxing :public Tuxing{ int ClacArea() { //.. return m_nLenth * m_nLenth; }private: int m_nLenth;};class CCircle:public Tuxing{};int main(){ CCircle obj; CZhengfangxing obj2; return 0;}
重载,重定义,虚函数定义
重载: 雷同作用域 函数名雷同 参数不同 调用的时候依据传参的不同,编译器主动调用相应的函数
重定义:继承关系中 函数名雷同 参数能够雷同也能够不雷同 子类对象默认调用本人的
虚函数:继承关系中 函数名雷同 参数雷同 须要加上virtual 应用特点:父类指针指向子类对象,调用虚函数,优先调用子类的
0.3 模板
0.3.1函数模板
template <typename M,typename N,typename L>void Fun(M a, N b, L c, int nLenth){}int main(){ Fun(1, 2.5, 'c', 100); return 0;}
模板的特化:
不能应用通用算法解决一些数据类型,能够为其独自实现算法。这个叫做特化
template <>void Fun(int a, int b, double c, int nLenth){}
0.3.2 类模板
咱们应用C语言的数组,它的长度只能是一个常量,不能动静扩大。应用起来不太不便。对于一些惯例的数组操作,都须要本人去实现。没有面向对象的反对,咱们实现一个动静数组,反对以下性能:
1.反对动静增长
2.反对任意数据类型
3.反对惯例的数组操作
(增 删 改 查)
#pragma once//先实现一个存储int类型的数组,元素如果最多100个template<typename T>class CMyArr{public: CMyArr(int nMax = 3); //减少一个数据 bool Insert(T nData, int nLoc); //删除一个数据 bool DeleteEle(int nLoc); bool ModifyByLoc(T nData, int nLoc); bool GetEleByLoc(int nLoc, T& Ele); //获取以后元素个数 int GetLenth(); bool sort();private: T* m_buf; int m_nLenth; int m_nMax;};template<typename T>CMyArr<T>::CMyArr(int nMax) :m_buf{ 0 }, m_nLenth(0), m_nMax(nMax){ m_buf = new T[nMax]{ 0 };}//减少一个数据template<typename T>bool CMyArr<T>::Insert(T nData, int nLoc){ //1. 检测传入的地位,是否正确 if (nLoc<0 || nLoc>m_nLenth) { return false; } //2. 是否缓冲区曾经满了 if (m_nLenth == m_nMax) { //如果缓冲区满了,那么就能够申请更大的空间,而后去存储 T* pTemp = new T[m_nMax * 2]{ 0 }; //将老缓冲区中的数据拷贝到新申请的缓冲区 for (int i = 0; i < m_nMax; i++) { pTemp[i] = m_buf[i]; } //开释原来的缓冲区 delete[]m_buf; m_buf = pTemp; m_nMax *= 2; } //3. 增加数据的地位,在结尾,间接增加 if (m_nLenth == nLoc) { m_buf[nLoc] = nData; m_nLenth++; return true; } //4. 增加数据的地位,在两头,须要挪动数据,再增加 for (int i = m_nLenth - 1; i >= nLoc; i--) { m_buf[i + 1] = m_buf[i]; } //曾经挪动完数据了,增加数据 m_buf[nLoc] = nData; m_nLenth++; return true;}//删除一个数据template<typename T>bool CMyArr<T>::DeleteEle(int nLoc){ //1. 检测地位是否正确 if (nLoc < 0 || nLoc >= m_nLenth) { return false; } //2. 删除的是结尾,不须要挪动 if (nLoc == m_nLenth - 1) { m_nLenth--; return true; } //3. 删除的是两头,就须要挪动 for (int i = nLoc; i < m_nLenth - 1; i++) { m_buf[i] = m_buf[i + 1]; } m_nLenth--; return true;}template<typename T>bool CMyArr<T>::ModifyByLoc(T nData, int nLoc){ //1. 检测地位是否正确 if (nLoc < 0 || nLoc >= m_nLenth) { return false; } //2. 地位没有问题,间接赋值 m_buf[nLoc] = nData; return true;}template<typename T>bool CMyArr<T>::GetEleByLoc(int nLoc, T& Ele){ //1. 检测地位是否正确 if (nLoc < 0 || nLoc >= m_nLenth) { return false; } //2. 地位没有问题,间接赋值 Ele = m_buf[nLoc]; return true;}//获取以后元素个数template<typename T>int CMyArr<T>::GetLenth(){ return m_nLenth;}template<typename T>bool CMyArr<T>::sort(){ for (int j = 1; j < m_nLenth; j++) { for (int i = 0; i < m_nLenth - j; i++) { if (m_buf[i] > m_buf[i + 1]) { T nTemp = m_buf[i]; m_buf[i] = m_buf[i + 1]; m_buf[i + 1] = nTemp; } } } return true;}
具体的应用:
#include <iostream>#include "MyArr.h"int main(){ CMyArr<int> obj; obj.Insert(10, 0); obj.Insert(20, 0); obj.Insert(30, 0); obj.Insert(100, 1); obj.Insert(200, 2); obj.DeleteEle(1); obj.ModifyByLoc(500, 1); obj.sort(); for (int i = 0; i < obj.GetLenth(); i++) { int nEle = 0; obj.GetEleByLoc(i, nEle); std::cout << nEle << " "; } CMyArr<char> obj2; obj2.Insert('a', 0); obj2.Insert('b', 1); obj2.Insert('c', 0); obj2.Insert('d', 1); obj2.Insert('e', 2); obj2.Insert('f', 1); for (int i = 0; i < obj2.GetLenth(); i++) { char nEle = 0; obj2.GetEleByLoc(i, nEle); std::cout << nEle << " "; } obj2.sort(); std::cout << std::endl; for (int i = 0; i < obj2.GetLenth(); i++) { char nEle = 0; obj2.GetEleByLoc(i, nEle); std::cout << nEle << " "; } return 0;}
STL -vector
1.1 vertor的根本应用
#include <iostream>#include <vector>#include <algorithm>using std::vector;int main(){ vector<int> obj; //1. 减少 //push_back 在结尾增加 //insert 在两头增加 obj.push_back(1); obj.push_back(2); obj.push_back(3); obj.push_back(4); obj.push_back(5); obj.push_back(6); //vector中应用迭代器来标识地位 //咱们能够暂且认为迭代器是一个指针 //能够有 + - *的操作 //获取起始地位的迭代器 vector<int>::iterator it1 = obj.begin(); obj.insert(it1+2, 100); //2. 删除 //pop_back 删除结尾 //erase 删除两头 //clear 全副删掉 obj.pop_back(); vector<int>::iterator it2 = obj.begin(); obj.erase(it2+3); //3. 查问 //反对下标运算 //size 获取元素个数 std::cout << obj[2]; std::cout << obj.size(); //4. 批改 obj[2] = 10; std::cout << std::endl; //5. 遍历 //第一种遍历形式 for (int i = 0; i < obj.size(); i++) { std::cout << obj[i]<<" "; } std::cout << std::endl; //第二种遍历形式 //obj.end()是结尾的迭代器,是最初一个元素的前面 vector<int>::iterator it3 = obj.begin(); for (; it3 != obj.end(); it3++) { std::cout << *it3 << " "; } std::cout << std::endl; //6. 排序 std::sort(obj.begin(), obj.end()); for (int i = 0; i < obj.size(); i++) { std::cout << obj[i] << " "; } std::cout << std::endl; return 0;}
1.2 应用vector实现一个密码本
#include <iostream>#include <vector>using std::vector;class CPassWordInfo{public: CPassWordInfo(const char* szWeb = nullptr, const char* szUserName = nullptr, const char* szPwd=nullptr) { strcpy_s(m_szWeb, 20, szWeb); strcpy_s(m_szUserName, 20, szUserName); strcpy_s(m_szPwd, 20, szPwd); } char* GetWeb() { return m_szWeb; } char* GetUserName() { return m_szUserName; } char* GetPwd() { return m_szPwd; } void SetWeb(const char* szWeb = nullptr) { strcpy_s(m_szWeb, 20, szWeb); } void SetUserName(const char* szUserName) { strcpy_s(m_szUserName, 20, szUserName); } void SetPwd(const char* szPwd = nullptr) { strcpy_s(m_szPwd, 20, szPwd); } bool Veryrify() { }private: char m_szWeb[20]; char m_szUserName[20]; char m_szPwd[20];};vector<CPassWordInfo> g_PwdBook;int main(){ //1. 用户输出要进行的操作 int nSelect = 0; while (true) { system("cls"); std::cout << "减少" << std::endl; std::cout << "删除" << std::endl; std::cout << "查问所有" << std::endl; std::cout << "批改" << std::endl; std::cout << "输出你的抉择(1~4):" << std::endl; std::cin >> nSelect; switch (nSelect) { case 1://减少 { char szWebSite[20] = { 0 }; char szUserName[20] = { 0 }; char szPwd[20] = { 0 }; //1. 输出站点的信息 std::cout << "站点:" << std::endl; std::cin >> szWebSite; std::cout << "账号:" << std::endl; std::cin >> szUserName; std::cout << "明码:" << std::endl; std::cin >> szPwd; //2. 构建一个对象,存储到vector CPassWordInfo obj(szWebSite, szUserName, szPwd); g_PwdBook.push_back(obj); break; } case 2://删除 { int nDelete = 0; std::cout << "请输出你要删除的序号:" << std::endl; std::cin >> nDelete; //删除的时候,须要传递迭代器 vector<CPassWordInfo>::iterator it = g_PwdBook.begin(); g_PwdBook.erase(it+nDelete); break; } case 3://查问所有 { vector<CPassWordInfo>::iterator it = g_PwdBook.begin(); for (; it != g_PwdBook.end(); it++) { std::cout << "站点:"<<(*it).GetWeb()<<" "; std::cout << "用户名:" << (*it).GetUserName()<<" "; std::cout << "明码:" << (*it).GetPwd()<<std::endl; } break; } case 4: { int nModify = 0; //1. 输出要批改的地位 std::cout << "要批改几号:" ; std::cin >> nModify; //2. 输出具体数据 char szWebSite[20] = { 0 }; char szUserName[20] = { 0 }; char szPwd[20] = { 0 }; //3. 输出站点的信息 std::cout << "站点:" << std::endl; std::cin >> szWebSite; std::cout << "账号:" << std::endl; std::cin >> szUserName; std::cout << "明码:" << std::endl; std::cin >> szPwd; //4. 进行批改 g_PwdBook[nModify].SetWeb(szWebSite); g_PwdBook[nModify].SetUserName(szUserName); g_PwdBook[nModify].SetPwd(szPwd); //5. 校验明码 g_PwdBook[nModify].Veryrify(); } default: break; } system("pause"); }}