C++个人 复习笔记

1、类成员属性在不同位置的不同权限:
        权限|位置  类外        类内           派生(继承的子类)
        公有:          √                √                √
        保护:          ×                √                √
        私有:          ×                √                ×
        总结:
                类外:只能访问公有成员
                类内:可访问所有成员
                派生:无法访问祖先类的私有成员

class People
{
/* 保护或者私有成员属性提供安全接口 */
public:
    string Name()const {
        return this->m_name;
    }
    void SetName(string name){
        this->m_name = name;
    }

    string Sex()const {
        return this->m_sex;
    }
    void SetSex(string sex) {
        if(sex == "男" || sex == "女")/*保护数据安全性*/
            this->m_sex  = sex;
    }

    int Age()const {
        return this->m_age;
    }
    void SetAge(int age) {
        this->m_age = age;
    }

protected:/*保护:派生类可继承,外部无法访问*/
   int m_sex;
   string m_name;
   int m_age;

};

2、子类可继承父类公有和保护的成员属性

        公有:  一般想让外界直接访问的之后使用公有权限, 类似接口函数
        保护:  既不想要外部访问,但是又想让派生类继承使用则使用保护权限
        私有:  只允许内部自己访问,派生无法访问

#include <iostream>
#include <string>
using namespace std;

class Parent
{
protected:/*保护:派生类可继承,外部无法访问*/
   string m_sex;
   string m_name;
   int m_age;
};

class Child :public Parent
{
public:
    /*子类继承父类公有和保护的成员属性*/
    Child()
    {
        this->m_sex = "女";
        this->m_age = 19;
        this->m_name = "李华";
        this->schoolId = 2410000008;
    }
    /*不能在类外访问,需要调用接口函数打印*/
    void Print()
    {
        cout<<this->m_name<<" "<<this->m_age
            <<" "<<this->m_sex<<" "<<this->schoolId<<endl;

    }
private:
    long long schoolId;
};



int main()
{
   Child child1;
   child1.Print();
    return 0;
}

3、构造函数和析构函数
        ​​​

        3.1构造函数:
        作用:用于申请空间时初始化处理
        定义:
                1.函数名与类名相同
                2.无返回值
                --->通过从上定义规则可以发现,构造函数可以拥有参数,则可实现重载
        3.2析构函数:
        作用:用于销毁时做释放处理
        定义:
                1.函数名与类名相同,但多了一个~号
                2.无参,无返回值
                --->然通过以上定义规则发现,析构函数无法重载

        3.3注意:
        如果用户没有提供构造和析构以及拷贝等函数则编译器默认提供
                1.无参构造
                2.拷贝构造(浅)
                3.析构函数
                4. =运算符函数

class People
{
pubilc:
    People(){}
}; 

People peo1;
People peo2(peo1);    /*拷贝构造*/
People peo3 = peo1;   /*拷贝构造*/

peo3 = peo2;          /*=号赋值运算符*/

4、深浅拷贝

        浅拷贝: 是值拷贝,浅拷贝中包含指针变量,则都是指向到同一片内存空间地址 
                        会造成:①一个操作多个对象 ②多次析构照成程序崩溃 
        深拷贝: 在堆区申请空间的操作都要实现 
                        注意:一般牵扯指针操作,都需要自己实现深拷贝

/*********补充*************/

5、初始化列表的使用:

        使用 “  :”开始,多参数用逗号隔

        三种权限均可使用初始化列表来初始化

        ①构造函数 用 初始化列表调用其他构造函数 -> 减少代码量 

        ②继承中的初始化列表使用   继承来的父类成员属性初始化(使用父类的有参构造)

class People
{
public:
   string m_name;
protected:
   string m_sex;
private:
   int m_age;

public:
    People(string name,string sex,int age)
        :m_name(name),m_sex(sex),m_age(age)
    {

    }
};

6、常量成员属性 常量成员函数 常对象的区别

        6.1常量成员属性:
                定义:在变量名之前加 const
                作用:只初始化赋值一次,以后无法更改,必须由 "初始化列表" 操作

        6.2常量成员函数:
                定义:在函数参数后加 const
                作用:该函数不可修改类成员属性值,只可访问   自己在函数中定义的变量可以修改
                注意:一般读取函数都会写成const常函数


        6.3常对象:只能访问常函数,后面set容器存放的都会变成常对象

class People
{
public:
    const int value;//常成员属性(变量)
    int temp;

    People():value(10)
    //1、常成员属性只能初始化一次,以后无法更改 只能用“初始化列表”操作赋值
    {

    }

    void Print()const
    //2、常成员函数
    {
        //访问 可以
        cout<<"value:"<<value<<endl;
        cout<<"temp"<<temp<<endl;
        //修改:不行
        //temp = 90;
    }

    void SetValue(int v)
    {
        temp = v;
    }
    int getTemp() const;
    void setTemp(int value);
};


int main(int argc, char *argv[])
{
    People peo1;
    const People peo2;    // 3、常对象,只能访问常函数
    peo1.Print();         //正常对象 调用 const   成员函数 √
    peo1.SetValue(99);    //正常对象 调用 非const 成员函数 √

    peo2.Print();         //常对象 调用 const   成员函数 √
    //peo2.SetValue(99);  //常对象 调用 非const 成员函数 ×
    return 0;
}

7、静态成员特征

        7.1公有特征:
                1.可以通过对象 或 类名访问
                2.所有对象公用同一静态变量空间
       7.2 静态成员属性:
                类内声明,类外初始化
                常用: 用作数据记录
                须知:
                1.所有对象共享同一份数据
                2.空间在编译阶段就已经分配
                3.静态成员不占用对象空间
        7.3 静态成员函数:

                类内声明类外实现也可以,类内实现也可以
                注意:静态成员函数不能使用非静态成员,所以也不能访问this指针
                常用:接口处理(数据集,固定参数"串口参数,摄像头参数,音频参数,网络参数等")

class People
{
public:
    static int s_value;     /*静态成员属性:类内声明,类外初始化*/
    int m_value;
public:
    People()
    {
        s_value++;
    }
public:
    static void GetValue()  /* 静态成员函数 */
    {
        cout << "s_value = " << s_value << endl;
        //cout << "m_value = " << m_value << endl; 静态成员函数不能使用非静态成员
    }

    static string GetIP()
    {
        return "IPV4 192.168.1.100";
    }

    static int GetMax(int value1,int value2)
    {
        return value1 > value2 ? value1 : value2;
    }
};

/** 静态成员属性类外初始化 **/
int People::s_value = 0;

8、友元

分类:

         ①类做友元

//一、类做友元
class House
{
    friend class Friend_v;       /*1. 类 友元声明*/

public:
    int m_zoulang = 1;  //走廊
protected:
    int m_keting = 2;   //客厅
private:
    int m_bedroom = 3;  //卧室
};

class Friend_v
{
public:
    
    /*******************方法①*******************/
    House house1;                /* 2.1 被友元的类 成员 当成 此类 成员 */
    int get_Bedroom()const       /* 2.2 调用this->被友元的类 成员.(私有|保护属性) */
    {
        return this->house1.m_bedroom;
    }

    /*******************方法②*******************/
    static void visit(House h)    /*3. 友元类的成员函数直接访问*/
    {
        cout<<"参观走廊"<<h.m_zoulang<<endl;
        cout<<"参观客厅"<<h.m_keting<<endl;
        cout<<"参观卧室"<<h.m_bedroom<<endl;
    }
};

int main()
{
    /* 方法① */
    Friend_v fri1;
    cout<<fri1.get_Bedroom()<<endl;

    /* 方法② */
    House hou1;
    Friend_v::visit(hou1);
    return 0;
}

        ②全局函数做友元

class House
{
    
    friend void detection(House value);    /* 1.全局友元函数  友元声明 */

public:
    int m_zoulang = 1;  //走廊
protected:
    int m_keting = 2;   //客厅
private:
    int m_bedroom = 3;  //卧室
};

void detection(House value)
{
    cout << "走廊:" << value.m_zoulang << endl;
    cout << "客厅:" << value.m_keting << endl;
    cout << "卧室:" << value.m_bedroom << endl;
}

int main()
{
    House hou1;
    detection(hou1);                      /* 2.调用全局友元函数 */

    return 0;
}

        ③类成员函数做友元

class House;                                               /* 2.提前空声明被友元函数 */

class Friend_Func
{
public:            /* 3.友元类的成员函数 在类内声明,类外实现(在被友元类 下面 类外实现)*/
    void visit_friend_func(House value);
    void not_friend(House value);
};

class House
{
    friend void Friend_Func::visit_friend_func(House value);/* 1.类函数  友元声明 */

public:
    int m_zoulang = 1;
protected:
    int m_keting = 2;
private:
    int m_bedroom = 3;
};

void Friend_Func::visit_friend_func(House value)            /* 4.成员函数的实现 */
{
    cout << "清洁走廊:" << value.m_zoulang << endl;
    cout << "清洁客厅:" << value.m_keting << endl;
    cout << "清洁卧室:" << value.m_bedroom << endl;
}

void not_friend(House value)
{
    cout<<"未在被友元类中声明,不可访问保护|私有属性"<<endl;
}

int main()
{
    House hou1;
    Friend_Func fri_func;
    fri_func.visit_friend_func(hou1);
    return 0;
}

9、运算符重载

        运算符可以被重载为全局函数(类外)、成员函数(类内)。一般倾向于重载为成员函数,这样能够较好地体现运算符和类的关系。

        注意:不可重载的运算符:

        .                :成员访问运算符

        .* 和 ->*    :成员指针访问运算符

        ::               :域运算符

        sizeof        :长度运算符

        ?   :            :条件运算符

        #                : 预处理符号

       (1) “+”运算符:

                类外:实现的时候,必须(满参数),直接调用函数名

                类内:类内实现,第一个参数不用填,使用this代替,直接调用函数名

class People
{
private:
    int m_age;
public:
    string m_name;

    People(string name = "",int age = 0)
        :m_name(name),m_age(age) {}
    void Print()
    {
        cout<<this->m_name<<" "<<this->m_age<<endl;
    }

    People operator +(People v)            /* 1.类内实现 */
    {                                      
        People temp;
        temp.m_name = this->m_name + v.m_name;
        temp.m_age = this->m_age + v.m_age;
        return temp;
    }
};

People operator +(People v1,People v2)     /* 2.类外实现 */
{                                          
    People temp;
    temp.m_name = v2.m_name + v1.m_name;
    //temp.m_age = v2.m_age + v1.m_age;    /* 类外实现无法访问私有属性 */
    return temp;
}

int main(int argc, char *argv[])
{
    People peo1("李华",17);
    People peo2("小美",23);
    People peo3,peo4;

    peo3 = peo1.operator +(peo2);        /* (a + b)等价于 a.operator - (b) */
    cout<<(peo1 + peo2).name<<endl;
    peo3.Print();

    peo4 = operator +(peo1,peo2);        /* c = a + b; 等价于 c = operator + (a,b);*/
    peo4.Print();
    //peo4 = peo1+peo2; /* +运算符 类内、外同时实现,不能直接使用 a + b形式,需使用函数名 */

    return 0;
}

        (2)“++”自加运算符:(单目运算符 分 前置和后置 (后置要加int占位))

                        ①int类型前置++规则如下:

                        int a;        ++(++a) int类型的变量可以连续前置自加

                        cout<<++(++a)<<" "<<a<<endl;        ++(++a)  a 两值相等

                        返回值应该是引用,不然返回值是临时变量,自加后成员属性的值并没有改变

People &operator ++()        /* 类内实现 */
    {
        this->m_age += 1;
        return *this;
    }

                        ②后置++:(括号内加int占位)

                        int a; (a++)++   ×不允许连续后置自加,且自加后为只读值,函数应该为常量函数

                        cout<<(a++)<<" "<<a<<endl;         (a++)   a   两值不等

                        

const People operator ++(int)        /* 类内实现 */
    {
        People temp(*this);
        this->m_age += 1;
        return temp;
    }

        (3)单目运算符: << , >> , & , | ^

People operator <<(int num)        /* 类内实现 */
    {
        People temp(*this);
        temp.m_age = temp.m_age << num;
        return temp;
    }

                单目运算符 高阶:

{   /* 类内实现: */
    /* 由于遇到了 extern ostream cout 整个程序只有一个流,所以需要权限和引用 */
    friend ostream &operator <<(ostream &out,const People &value)
    {
        out << value.m_name << "\t"
            << value.m_age << "\t"
            << value.m_sex;
        return out;
    }


    friend istream &operator >>(istream &in,People &value)
    {
        cout << "请输入姓名 性别 年龄:";
        in >> value.m_name >> value.m_sex >> value.m_age;
        return in;
    }
};

int main()
{
    People peo5,peo6;
    cin >> peo5;              //输入
    cout << peo6 << endl;;    //输出
    return 0;
}

        (4)其他操作符:“ ()”,仿函数,通常做算法策略

                仿函数,谓词

    void operator ()(/*参数列表*/)
    {
        cout << "仿函数策略" << endl;
    }
    bool operator ()(int value)             /* 一元谓词:一个参数 */
    {
        if(value == 1) return true;
        return false;
    }
    bool operator ()(int value1,int value2) /* 二元谓词:两个参数 */
    {
        if(value1 == value2) return true;
        return false;
    }

        (5)其他操作符:“ [ ] ”

{   /* 类内实现: */
     int addr_len = -1;
    int addr_max = 10;
    int &operator [](int index)
    {
        return this->addr[index];
    }

    const int operator [](string com)
    {
        if(com == "max") return addr_max;
        if(com == "len") return addr_len;
        return 0;
    }
};

int main()
{
    people[3] = 5;         /* 相当于 people.addr[3] = 5 ,解读当前想要操作的是int addr[3]*/

    for(int i = 0; i < people["max"];i++)
    {
        cout << people[i] << ",";
    }
    cout << endl;
    return 0;
}

        (6)其他操作符 ”  ->  ”指针操作符:

{    
    /* 类内实现: */
    class Grade             /* 类内部类 */
    {
    public:
        int language;
        int math;
    };

    Grade grade = {         /* 结构体定义时直接赋值 */
        .language = 10,
        .math = 20
    };

    Grade *operator ->()
    {
        return &(this->grade);
    }
};

int main()
{
    People peo7;
    peo7->language = 100;    /* peo7.grade.language = 100; */
}

10、继承:(构造函数可相互调用)

People::People(string name,string sex,int age)
    :m_name(name),m_sex(sex),m_age(age)
{ }

/***************************************************************************************/
Student::Student(string id, string name, string sex, int age)
    //:m_ID(id),People(name,sex,age),m_grade{0,0,0}
    :Student(id,0,0,0,name,sex,age)                                   /*构造函数相互调用*/
{ }

Student::Student(string id, float language, float math, float english, string name, string sex, int age)
    :m_ID(id),People(name,sex,age),m_grade{language,math,english}
{ }

Student::Student(string id, Grade grade, string name, string sex, int age)
    :Student(id,grade.language,grade.math,grade.english,name,sex,age) /*构造函数相互调用*/
{ }

11、多继承成会产生的问题:

(1)父类成员同名   实习生 继承 学生和工人   使用类域调用解决
(2)菱形继承
                   people 
        student         worker <- : public virtual people
                   trainee
会重复继承相同的people 造成空间浪费,使用虚继承解决(生成虚表索引,虚指针 32位机占4字节)

class People
{
public:
    string m_name;
    int m_age;
};

class Student : virtual public People
{
public:
//    string m_name;
//    int m_age;
    float m_score;

    void Study(){cout<<"学习"<<endl;}
    void Exam(){cout<<"考试"<<endl;}
};

class Worker :  public virtual People
{
public:
//    string m_name;
//    int m_age;
    int m_salary;

    void work(int hour){cout<<hour<<"work"<<endl;}
};

class Trainee: public Student , public Worker
{
public:
    void sleep(){cout<<"zzzZZzzzZZZZZzZ..."<<endl;}
};

int main(int argc, char *argv[])
{
    cout<<sizeof(string)<<endl; //24字节
    cout<<sizeof(People)<<endl; //28字节

    cout<<sizeof(Student)<<endl; //People28 + float4 + 虚表索引4字节
    cout<<sizeof(Worker)<<endl; //People28 + int4 + 虚表索引4字节

    cout<<sizeof(Trainee)<<endl; //Student32+4 + Worker32+4 -Peole28字节

    Trainee tra1;
    tra1.m_name = "aaa";
    cout<<tra1.Trainee::m_name<<endl;;
    cout<<tra1.Worker::m_name<<endl;;

    return 0;
}

12、多态:
实现方法:

  1. 必须在继承体系下
  2. 子类必须要对父类中方法进行重写
  3. 通过父类的引用调用重写的方法

 存在的问题:
        一般在父类指针指向子类对象 (实现多态) delete时 会造成内存泄漏,可以使用虚析构或纯虚析构解决实现

class A
{
public:
    A(){cout<<__func__<<endl;}
    virtual ~A(){cout<<__func__<<endl;}
};

class B : public A
{
public:
    B(){cout<<__func__<<endl;}
    ~B(){cout<<__func__<<endl;}
};
/*无virtual    加virtual后
    A           A
    B    ->     B
    ~A          ~B
                ~A
 */
int main(int argc, char *argv[])
{
    A *a1 = new B;
    delete a1;
    return 0;
}

13、文件操作
        文件流类 头文件:#include <fstream>

(1)打开文件:
           void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out)
           void open(const std::string& __s,ios_base::openmode __mode = ios_base::in | ios_base::out)
        参数:
                @char* __s: C语言风格文件名
                @string s : C++风格文件名
                @ios_base::openmode mode : 打开模式
                    ios_base::in          写模式
                    ios_base::out        读模式
                    ios_base::trunc     创建(清空写)
                    ios_base::binary   二进制
                    ios_base::app 追加

    fstream fd;                  /* 1.实例化对象 */
                                 /* 2.打开文件,当前路径下清空写 */
    fd.open("test.txt",ios_base::trunc | ios_base::in | ios_base::out);
    /* Qt中先要配置左侧“项目”中的路径,红色路径表示不能使用,shadow build不要勾选 */

    if(fd.is_open() == false)    /* 3.判断是否打开成功 */
    {
        cout <<"文件打开失败"<< endl;
    }

(2)读写操作

        格式化读取:        operator >>
        格式化写入:        operator <<
 

class Student
{
public:
    Student(string name = "",int age = 0):m_name(name),m_age(age){}
    string m_name;
    int m_age;
};

Student stu1("李华",18);
Student stu2("小美",19);
Student stu3;
fd <<stu1.m_name<< " " <<stu1.m_age<< endl;  /* 格式化写入 */
fd <<stu2.m_name<< " " <<stu2.m_age<< endl;

while(fd.eof() == false)
{
    Student stu3;
    fd >> stu3.m_name >> stu3.m_age;         /* 格式化读出,写入时的空格做变量分割 */
    if(stu3.m_age != 0)
        cout << "姓名:" << stu3.m_name << "\t年龄:" << stu3.m_age << endl;
}

        块写入:        write(const char_type* __s, streamsize __n)
        块读取:        read(char_type* __s, streamsize __n)

char buf[128] = "你好";
fd.write(buf,128);               /*写入一块*/

char buf[128] = "";
fd.read(buf,128);                /*读出一块 并写入buf*/
cout << "buf = " << buf << endl;

        字节写入:         put(char_type __c)
        字节读取:        int_type get()

char buf[128] = "abcdefg";
for(int i = 0; i < strlen(buf);i++)
{
    fd.put(buf[i]);            /* 用循环依次写入 */
}

char ch = 0;
while(fd.eof() == false)
{
    ch = fd.get();            /* 用循环依次读出,并用ch接收打印 */
    cout << ch;
}

        读取一行:         getline(char_type* __s, streamsize __n)

char buf[128] = "";
fd.getline(buf,128);

fd.close();            /* 关闭文件 */

(3)关闭文件: fd.close();

容器:

14、vector
          头文件:#include <vector>
          构造: vector() 无参构造
                      vector(const vector &stl);                    拷贝构造
                      vector(Iterator begin,Iterator end);      区间赋值构造
                      vector(int count,Type value);               N个值赋值
                      经常用的构造: 无参 和 区间赋值构造
          析构: ~vector()
          赋值:      =号赋值运算符重载
                        assign()函数                                      ------- 支持区间
          插入和删除:
                        push_back()                                       尾部插入
                        pop_back()                                         尾部删除
                        insert(iterator pos,Type value)            任意插入-----支持区间
                        erase(iterator begin,iterator end)        任意删除 删除指定迭代器位置 或 迭代器区间
                        clear()                                                 清空容器
          访问:
                       int index;
                       v.at(index)
                       v[index](运算符重载)
                       v.front()
                       v.back()
          迭代器: vector连续空间->随机访问迭代器->可使用 ++,--,[]
                         v.begin(),v.end() -> [ )左闭右开 
                         注意:v.end()是最后一个元素后的位置,所以没有值
                         v.front()  v.begin()
                         v.back()   (--v.end())
           使用for_each:
                       for_each(_InIt _First, _InIt _Last, _Fn _Func)
                        注意事项:一般算法库,策略函数参数,传参类型都是Type变量类型,for_each有三个参数,前两个参数用来确定一个区间,第三个参数则是操作方式lambda,函数对象(仿函数)或者普通函数都可以充当其第三个参数。

int main(){
    vector<int> v1,v2;                /* 实例化vector对象 */
    v1.push_back(1);                  /* push_back 插入数据 */
    v1.push_back(4);
    v1.push_back(9);
                                      /* insert 插入数据 */
    v2.insert(v2.begin(),v1.begin(),v1.end());
    v2.insert(v2.begin(),10,1);
    v2.insert(v2.begin(),99);
    
    for(int i = 0;i < v1.size();i++)
    {
        cout<< v1[i] <<",";           /* ①v[index]访问*/
    }
    cout<< endl;
    
    vector<int>::iterator it = v1.begin();
    for(;it != v1.end();it++)         /* ②迭代器访问 */
    {
        cout<< *it <<",";             /* (*it) => <类型> 尖括号内类型 */
    }    
    cout<<endl;
}

三种for_each实现:

int main()                                    /* ③for_each 实现 */
{
    class Print
    {
    public:
        void operator()(int value)            /* 仿函数 */
        {
            cout<<value<<",";
        }
    };
    /* Print pri1; for_each(v1.begin(),v1.end(),pri1); Print()为匿名对象 */
    for_each(v1.begin(),v1.end(),Print());

    void Print_int(int value);                /* 普通函数:内部声明*/
    for_each(v1.begin(),v1.end(),Print_int);

    for_each(v1.begin(),v1.end(),[](){        /* lambda*/
    
        /* 实现 */
    });
}

void Print_int(int value)
{
    cout << value << ",";
}

         谓词:
                1、返回bool类型的仿函数称为谓词
                2、如果operator()接受一个参数,那么叫做一元谓词
                3、如果operator()接受两个参数,那么叫做二元谓词

         vector容量和大小:
                empty()           判断容器是否为空
                capacity()        容器的容量
                size()               当前容器的元素个数
                resize()            重新指定容器的长度
                reserve()          预留空间 < ----- > 非常有必要

        发现结果: 数据容量成指数增长,
                缺点:①照成空间浪费 ②每次增长浪费时间
                解决方案:开局就指定空间大小 <------> 提前分配空间

          vecto r优点: 访问快,尾删和尾增快
          vector 缺点: 非尾删和非尾增效率低,增加元素需要申请新空间并拷贝,浪费效率不适合(排序等需要改变的算法)    

vector<int> v;
v.reserve(10001);

                存放自定义类型:        Person成员: 姓名 + 年龄
                (要注意数据结构中对自定义类型的支持:运算符重载实现)

class Person
{
public:
	Person(string name = "",int age = 0):m_name(name),m_age(age){}
	string m_name;
	int m_age;
private:                                        /* friend打破封装,可无视private */
	friend ostream &operator <<(ostream &out,Person person)
	{
	    out << person.m_name << "\t"
	    << person.m_age;
	    return out;
	}
};
 
vector<Person> v;                               /* 实例化STL对象 */
v.push_back(Person("李华",17));                 /* 插入数据 */
v.push_back(Person("李明",18));
//auto 自动类型推导  iterator begin()
for(auto it = v.begin() ; it != v.end() ;it++)
{
	cout << *it << endl;                        /* 输出数据 */
}

15、deque 双端数组

         头文件:#include <deque>
          构造: deque() 无参构造
                        deque(const deque &)拷贝构造
                        deque(iterator begin,iterator end)区间构造
                        deque(int count,Type value) N个值赋值构造
          赋值:      =号赋值运算符重载
                        assign()函数                                      ------- 支持区间
          插入和删除:
                        push_back()                                       尾部插入
                        push_front()                                       头部插入
                        pop_back()                                         尾部删除
                        pop_front()                                         头部删除
                        insert(iterator pos,Type value)            任意插入-----支持区间
                        erase(iterator begin,iterator end)        任意删除 删除指定迭代器位置 或 迭代器区间
                        clear()                                                 清空容器
          访问:
                       int index;
                       d.at(index)
                       d[index](运算符重载)
                       d.front()
                       d.back()
          迭代器: 支持迭代子遍历

vector<int> v1;
deque<int> d1(v1.begin(),v2.end());    /* 可以支持不同容器 */

             通用容器打印函数(使用模板):

template <class Type>
void Print(Type &v)
{
    for(auto it = v.begin(); it != v.end();it++)/*auto 是自动根据 = 返回值类型做生成 */
    {
        cout << *it << ",";
    }
    cout << endl;
}
    deque<int> v;
    for(int i = 0; i < 10;i++)
    {
        v.push_back(i);     /*尾部插入 */
        v.push_front(i);    /*头部插入 */
    }
    v.insert(v.begin(),3,600);
    /* 600,600,600,9,8,7,6,5,4,3,2,1,0,0,1,2,3,4,5,6,7,8,9 */

    cout << "删除数据:" << endl;
    v.pop_back();           /*尾部删除*/
    v.pop_front();          /*头部删除*/
    /* 600,600,9,8,7,6,5,4,3,2,1,0,0,1,2,3,4,5,6,7,8 */

    v.erase(++v.begin(),--v.end()); /* 指定删除 */
    /* 600,8 */

    cout << v.size() << endl;       /* 元素个数 */
    cout << v.empty()<< endl;       /* 是否为空 */

    for(size_t i = 0; i < v.size() ;i++)
    {
        //cout << v[i] << " ";      /* [] 运算符重载 */
        cout << v.at(i) << " ";     /* at 下标访问 */
    }

使用算法库sort排序:
void sort(首迭代子,尾迭代子)  ->                        排序规则:默认升序,使用 >或< 运算符重载
void sort(首迭代子,尾迭代子,二元谓词)  ->        排序规则:默认升序

void test()
{
    deque<int> v;
    for(int i = 0; i < 10;i++)
    {
        v.push_front(i);
    }

    sort(v.begin(),v.end());                    /* ①使用默认sort排序 */

    bool cmp_int(int value1,int value2);        /* 回调函数内部声明 */
    sort(v.begin(),v.end(),cmp_int);            /* ②回调函数机制自定义规则 */

    class CMP_INT
    {
    public:
        bool operator()(int value1,int value2)  /*二元谓词*/
        {
            return value1 > value2;
        }
    };
    //CMP_INT temp;sort(v.begin(),v.end(),temp);/* ③仿函数机制自定义规则 */
    sort(v.begin(),v.end(),CMP_INT());  //CMP_INT()匿名对象
}

bool cmp_int(int value1,int value2)            /* 回调函数外部实现 */
{
    return value1 < value2;
}

                存放自定义类型:

class People
{
public:
    People(string name = "",int age = 0) : m_name(name),m_age(age){}
    bool operator <(/*this,*/const People &value) const /* < 比较运算符重载 */
    {
        return this->m_age < value.m_age;
    }
    int age() const;
protected:
    string m_name;
    int m_age;
};

int People::age() const
{
    return m_age;
}

void main()
{
    deque<People> v;
    string names[] = {"李华","李化","李花"};
    int ages[] = {18,20,17};
    for(int i = 0; i < 3;i++)
    {
        People people(names[i],ages[i]);
        v.push_back(people);
    }

    sort(v.begin(),v.end());                /* ①默认升序,使用 < 比较运算符重载 */

    class CMP_People
    {
    public:
        bool operator()(People value1,People value2)
        {
            return value1.age() < value2.age();
        }
    };
    sort(v.begin(),v.end(),CMP_People());   /* ②使用自定义策略:二元谓词 */
}

      16、list 链表容器:
                构造:
                        assign(beg, end);         将[beg, end)区间中的数据拷贝赋值给本身
                        assign(n, elem);           将n个elem拷贝赋值给本身
                        list& operator=(const list &lst); 重载等号操作符
                        swap(lst);                     将lst与本身的元素互换
                容器大小:
                        size();                     返回容器中元素的个数
                        empty();                 判断容器是否为空
                        resize(num);          重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
                        resize(num, elem);     重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
                插入和删除:

                        push_back(elem);         尾部加入一个元素
                        pop_back();                   删除最后一个元素
                        push_front(elem);          在开头插入一个元素
                        pop_front();                   移除第一个元素
                        insert(pos,elem);           在pos位置插elem元素的拷贝,返回新数据的位置。
                        insert(pos,n,elem);        在pos位置插入n个elem数据,无返回值。
                        insert(pos,beg,end);      在pos位置插入[beg,end)区间的数据,无返回值。
                        clear();                           清除
                        erase(beg,end);             删除[beg,end)区间的数据,返回下一个数据的位置。
                        erase(pos);                    删除pos位置的数据,返回下一个数据的位置。
                        remove(elem);               删除容器中所有与elem值匹配的元素。

               反转和排序:
                        reverse();           反转链表
                        sort();                 链表排序

class People
{
public:
    People(string name = "",int age = 0,string sex = "女",int height = 0);
    string name() const;
    int age() const;
    string sex() const;
    int height() const;

    bool operator <(/*this*/ const People &people) const
    {
        return this->m_age < people.m_age;
    }

    bool operator ==(/*this*/ const People &people) const
    {
        return this->m_name == people.m_name;
    }
protected:
    string m_name;
    int m_age;
    string m_sex;
    int m_height;
private:
    friend ostream &operator <<(ostream &out,const People &people)
    {
        out << people.m_name << "\t" << people.m_age << "\t" << people.m_sex << "\t" << people.m_height;
        return out;
    }
};

void test0()
{
    list<People> v;
    string names[] = {"李华","李花","李化","立华","黎华"};
    int ages[] = {18,29,31,18,30};
    string sexs[] = {"男","女","男","男","女"};
    int heights[] = {160,175,183,159,165};

    for(int i = 0; i < 5;i++)
    {
        v.push_back(People(names[i],ages[i],sexs[i],heights[i]));  /*匿名对象 */
    }
    list<People>::iterator it;                                     /*定义迭代器*/
    for(it = v.begin(); it != v.end() ; it++)
    {
	    cout << *it << endl;                                 /* 打印数据<<重载 */
    }    
}

                list自带 sort 排序有两个:void sort(); void sort(二元谓词); 

void test1()
{
    v.sort();           /* ①list自带排序规则: 使用<运算符重载 */
    v.reverse();        /* 链表反转 */

    class CMP_People
    {
    public:
        bool operator()(const People &people1,const People &people2)
            if(people1.age() == people2.age()) //年龄相同
            {
                return people1.height() < people2.height(); //比较身高
            }
            return people1.age() < people2.age();
        }
    };

    v.sort(CMP_People()); /* ②二元谓词规定排序规则*/
}

                查找:find( begin() , end() ,参考变量指定的排序规则)  
                                                   查找第一个匹配的元素,并返回当前迭代子
                           find_end          找到最后一个匹配的元素
                           find_first_of     找到第一个匹配的元素
                           find_if              找到第一个匹配一元谓词的元素
                           find_if_not       找到第一个匹配的一元谓词的元素
                        返回值:
                             找到:返回非 end尾迭代子
                             未找到: end尾迭代子
                        注意:需要 == 判断运算符重载

/* class People
{
    .....
    bool operator ==((this默认值,可省略) const People &people) const
    {
        return this->m_name == people.m_name;
    }
    .....
};    */
void test3()
{
    it = find(v.begin(),v.end(),People("李华"));    /* 匹配姓名 ==重载 */
    if(it != v.end())
    {
        cout << "找到了" << endl;
        cout << *it << endl;
    }
    else
        cout << "未找到" << endl;

    class CMP_People1
    {
    public:
        bool operator()(const People &people)      /* 匹配性别 仿函数指定规则 */
        {
            return people.sex() == "男";
        }
    };

    for(it = v.begin(); it != v.end() ; it++)
    {
        it = find_if(it,v.end(),CMP_People1());    /* find_if找到第一个匹配一元谓词的元素*/
        if(it != v.end())
        {
            cout <<"it != v.end()"<< *it << endl;
        }
        else
            break;
    }
}

17、string容器:
                构造:string()         无参
                string(str)                 拷贝构造
                string( str, pos, n )   指定位置个数拷贝{区间}
                string(Char*)            C字符指针
                string(n, Char)         多个字符
                string(beg, end)      迭代子区间

       string->vector <char>:
                vector<char> v(str3.begin(),str3.end());

void test0()
{
    string str1;                /*无参构造*/
    string str2(str1);          /*拷贝构造*/
    string str3("hello world"); /*C字符指针*/
    string str4(str3,1,2);      /*指定位置 个数拷贝{区间}*/
    string str5(10,'A');        /*多个字符*/

    vector<char> v(str3.begin(),str3.end());
    string str6(v.begin(),v.end());
    string str7(str3.begin(),str3.end());
}

        赋值:

       =号赋值: 类似C字符串库的 strcpy
                string&operator=(str)            C++风格
                string&operator=(Char*)      C风格
                string&operator=(c)              单字符

        assign赋值: 类似C字符串库的 strncpy
                string&assign(first, last)                 区间
                string&assign(str)                          C++风格
                string&assign(str, pos, n)               类似 strncpy C++格式
                string&assign(Char* ,n)                 类似 strncpy C格式
                string&assign(const _CharT* __s) 类似 strcpy C格式
                string&assign(n, Char)                   多字符

void test1()
{
    string str("hello");
    string str1;
    str1 = str;                          /*C++风格*/
    str1 = "hello world";                /*C风格*/
    str1 = 'N';                          /*单字符*/

    str1.assign(str.begin(),str.end());  /*区间*/
    str1.assign(str);
    str1.assign(str,0,2);                /*C++风格strncpy*/
    str1.assign("hello wrold",5);        /*C风格strncpy*/
    str1.assign("hello wrold");          /*C风格strcpy*/
    str1.assign(100,'6');                /*多字符*/
}

        转换:
        类似于C库中的转换形式 atoi , atol , itoa ,ltoa, dtoa

                数值转string:
                        string to_string(double);
                        string to_string(flaot);
                        string to_string(int);
                        ...
                string转数值:
                        double stod();
                        flaot stof();
                        int stoi();
                        ...
                 string转char*指针:
                        内部.data()

void test2()
{
    int value_int = stoi(string("-10"));        /*string 转数值*/
    double value_double = stod(string("15.6"));

    string str;                                 /*数值 转string*/
    str = to_string(165);
    str = to_string(165.56);

    char buf[128];
    strcpy(buf,str.data());                     /*string 转char* */
}

        拼接:

                += 运算符重载     类似 strcat
                append()              类似 strncat 和 strcat

void test3()
{
    string str;
    str += 'A';
    str += string("李华");
    str += "骊骅";
                                        /*append*/
    str.append(str.begin(),str.end());  /*区间*/
    str.append(10,'A');
    str.append("狸花");
}

查找和替换和子串
        查找:find  类似C库的 strchr(char) 和 strstr(char)
        返回值:下标
              未找到:-1
              找到:!= -1
        替换: replace   插入式覆盖 又是类似于 assign 的参数,增加下标
       子串: string substr(); ,操作类似strncpy + strstr

void test4()
{
    string str("hello world");
                                
    int index = 0;
    index = str.find('P');                        /*查找*/
    int index_head = str.find("wo");
    int index_end = str.find("ld");

    str.replace(0,5,"helloooooooo! world");       /*替换*/
    
    index_head += strlen("world");
    string v = str.substr(index_head,index_end-index_head);/*子串*/
}

100、QT成员名在相应源文件生成函数 方法:

101、

多文件操作:
 .h
#include <iostream>
using namespace std;
class

.cpp
#include " .h"
函数实现。。。
接口函数设为常函数

main.cpp
#include<iostream>
#include <list>
#include " .h"

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值