乐趣区

关于c++:小凯15天快速讲完c语言简单学习第十二课

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");
    }
}
退出移动版