瞭解c++知識

轉載:https://blog.csdn.net/luanpeng825485697/article/details/76537402轉載的目的主要是爲了學習。

此demo主要包括三個文件:namespace.h文件,包含了自定義空間、空間函數、空間變量、空間自定義類;namespace.c文件爲namespace.h文件中定義函數的實現;main.cpp文件爲主程序運算。

namespace.h和namespace.cpp包含了自定義基、繼承類、模板類的定義及實現。涉及到自定義類的構造函數、重載構造函數、函數默認值、析構函數、複製構造函數、重載運算符(賦值函數、加法函數)、虛函數、常值函數、靜態函數、靜態變量、常值變量、枚舉變量、內部類、訪問修飾符、繼承、重寫虛函數、基類引用、不定參數函數、友函數、友類、類型引用、終態函數、終態類、模板變量等內容。

namespace.h文件

#pragma once  //防止文件被多重包含
#include <stdio.h>
#include <iostream>  //數據流
#include <string>  //字符串
#include <exception>  //異常
#include <stdarg.h>  //變化參數
#ifndef PI   //如果沒有定義PI則定義,否則跳過  避免重複包含
#define PI 3.1415926
#endif
using namespace std;  //常用空間函數
//自定義命名空間
namespace mynamespace
{
//靜態整型
static long long timenow;
//自定義函數
void myfun(string str);                                 

//自定義類-學生類
class Student
{
public:                                                             //公共成員,外部可以訪問的成員
    Student();                                                      //無參構造函數   //默認構造函數(參數全有默認值+無參函數)可以無參調用
    Student(string name,int age=default_age);                       //有參構造函數   //函數名相同,方法重載,age含有默認參數,此參數可有可無
    Student(int age);                                               //有參構造函數 //函數名相同,方法重載,函數名相同,參數類型和數量不同的爲重載,與返回值無關
    virtual ~Student();                                                //析構函數  //銷燬對象時,自動調用該函數,該方法用來釋放內存,最好設爲虛函數,這樣多態特性,能銷燬派生類對象創建的內存
    Student(const Student& another);                                //複製構造函數
    Student& operator=(const Student& another);                     //重載賦值運算符,在函數內生成類對象的就要返回類,沒有生成類對象的返回類引用
    //可以重載關係運算符 算數運算符  遞增遞減運算符  按位運算  二元邏輯運算符  插入<<運算符  提取>>運算符  下標運算符  函數調用運算符  解除引用運算符  內存分配和釋放運算符
    Student operator+(const Student& another) const;                //加法運算符重載  Student的加法運算,const函數不改變類內成員,返回對象不返回引用是因爲生成了一個新的對象,與原對象並列存在
    Student operator+(const string& anothername) const;             //加法運算符重載   避免重載時的隱式轉化 +必須在Student的後面。對象名稱既可以作爲對象返回,又可以作爲對象引用返回
    virtual void setname(string name);                              //virtual關鍵字,虛函數,支持派生類重寫,最好所有函數都設置爲虛函數,java就是這麼做的
    string getname() const;                                         //不改變數據成員的函數聲明爲const
    void setage(int age);                                           //常規函數聲明
    static int getage();                                            //static關鍵字,靜態函數,靜態方法不能重寫,不存在繼承  //靜態方法屬於定義它的類的名稱,不屬於特定的對象,調用時使用名字解析
    static string default_name;                                     //靜態數據,存儲在靜態區
    static const int default_age=18;                                //const關鍵字,常值數據,數據存儲在文字常量區,const數據定義時需要賦值。
                                                                    //mutable標記的爲可變變量   在const函數中可以改變值的變量
    enum allsex{boy,girl};                                          //enum關鍵字,枚舉類型,用於限定參數的取值範圍,相等於define,或者const
    class sex{                                                      //定義內部類,性別
    public:
        string getsex();   
        void setsex(allsex sextype);                                //使用枚舉類型作爲參數
    private:
        string sexstr;
    };
protected:                                                          //派生類可以訪問的成員
    string name;
private:                                                            //只能在類內訪問的成員
    int age;
};


//派生類-班長類
 class Monitor:public Student                                       //公有繼承   public代表基類的最高訪問權限  所有操作的權限自動降級爲此權限  儘量使用public
 {
 public:
     Monitor(){                                                     //構造函數不能繼承
         this->task = "幫助老師管理班級";                           //函數定義可以直接在聲明中實現,也可以在對象cpp中實現,也可以不實現,在調用時實現
         name="monitor";
         cout<<"無參派生類構造函數"<<endl;                           //cout<<           <<endl; 輸出內容到dos窗口
     };    
     virtual void setname(string name) override                     //override,重寫虛方法  virtual、override可以不寫,override寫上以便與隱藏函數混淆
     {
         this->name=name;                                           //this作爲對象Student
         cout<<"派生類設置名稱參數:"+name<<endl;
     }
     using Student::getname;                                        //包含基類函數,使用using關鍵字顯示的包含基類中定義的同名的所有版本的方法,包含後相當於在當前內中展開
     string getname(string surname)                                 //創建新成員函數,與基類形成重載  因爲參數不同,若不使用using包含,則會隱藏基類函數
     {
         cout<<"派生類獲取名稱參數:"+surname+name<<endl;
         return surname+name;
     }
     void setage()                                                  //隱藏基類函數,與基類函數同名
     {
          age=7;
          cout<<"派生類設置年齡參數:"<<age<<endl;
     }
     int getage(){                                                  //創建對象成員函數,基類中的函數爲靜態函數,不屬於對象,屬於類
         cout<<"派生類讀取年齡參數:"<<age<<endl;
         return age;
     };
     string gettask(){return task;};                                //創建對象成員函數
     void settask(string task,...){                                 //...表示不定長的參數數目。創建對象成員函數
         va_list arg_ptr;                                           //定義參數列表
         va_start(arg_ptr,task);                                    //將參數列表起始位置綁定爲第一個參數
         string aa=" ";
        // while (aa!="" && !aa==NULL)                              //無法對參數列表個數或結尾進行判斷,必須自己傳入特性參數來代表個數或結尾
         {
             aa = va_arg(arg_ptr,string);                           //迭代讀取參數,並轉化爲相應的類型
         }
         va_end(arg_ptr);                                           //參數清理工作
         this->task = task;
     };                 
 private:
     int age;                                                       //基類中age爲private,派生類無法訪問,派生類重新定義
     string task;                                                   //添加派生類自有屬性
 };





 //自定義類-老師類
 class Teacher
 {
 public:
     Teacher():name("teacher"),course("語文"){                        //基類的默認構造函數,同時初始化數據成員name、course
         cout<<"基類無參構造函數:"+name<<endl;
     }; 
     Teacher(string name){cout<<"基類有參構造函數:"+name<<endl;};   //基類的有參構造函數
     ~Teacher(){cout<<"基類析構函數"<<endl;};                        //析構函數
     friend class Student;                                          //友元,Student 類中所有的方法可以訪問Teacher的private、protected、public數據成員和方法
     friend void Student::setname(string name);                     //只有設置友元的函數可以訪問當前類的成員和方法,只有Student:;setname函數可以訪問Teacher的成員方法
     virtual Student& getstudent()=0;                               //=0代表爲純虛函數,沒有定義方法,只是聲明瞭方法,包含純虛函數的類爲抽象類,抽象類不能實例對象
     virtual void setstudent(Student& students) =0;                 //&爲引用,相當於變量別名
     virtual string getname() final{                                //final函數,禁止重寫,用在派生類再次被繼承後重寫的情況下; 
         cout<<"基類獲取名稱參數:"+name<<endl;return name;};  
     virtual void setname(string name="teacher"){this->name = name;}; 
 private:
     virtual string getcourse(){return course;};                    //c++中,private函數也可以虛化重寫,java中只能重寫public和protect方法//繼承時可以修改訪問限制符
     string name;
 protected:
     string course;
 };



 //創建班主任類
 class Headmaster final:public Teacher          //final標記的類不能被繼承
 {
 public:
     //using Teacher::Teacher;                                      //構造函數不能繼承,只能顯示調用
     Headmaster(){cout<<"派生類無參構造函數:headmaster"<<endl;}; //派生類的構造函數  調用前會自動調用基類的默認構造函數
     Headmaster(string name):Teacher(name){                         //派生類的構造函數,調用前會調用顯示引用的基類構造函數
         cout<<"派生類有參構造函數:"+name<<endl;
     };  
     ~Headmaster(){cout<<"派生類析構函數"<<endl;};                    //析構函數
     //使用時,默認參數取值根據指針類型  函數方法根據指向對象
     //virtual void setname(string name="headmaster") override;     //派生類的構造函數  沒有using時  默認爲重寫了所有版本   有using時,表示重寫了當前版本   派生類可以使用不同的默認參數
     virtual Student& getstudent() override{return student;};       //記得添加override,因爲基類改變,派生類沒改變會報錯,這樣提醒修改派生類
     virtual void setstudent(Student& students) override{           //應該重寫,重載方法的,所有版本。虛函數可以不重寫,重寫不重寫都保持函數虛化特性
         this->student = student;}; 
     virtual string getcourse() override{return course;};           //重寫基類的private函數,並修改訪問修飾符

 private:
     Student student; 

 };

 };


 template<class TT=int> 
 class classA{                              //template<class T>爲模板,類型T爲不確定類型,classA爲類模板,可以爲不定類型設置默認值,但是在使用類定義示例時,仍然需要使用<>
 public:
     TT add(TT tt,TT pp);                                           //使用模板函數
     template<class TT> TT plus(TT tt,TT pp){                       //在類模板內部定義函數
         return tt+pp;
     }
 };

自定義空間namespace.app文件

#pragma once  //防止文件被多重包含
#include <stdio.h>
#include <iostream>  //數據流
#include <string>  //字符串
#include "namespace.h"
using namespace std;
using namespace mynamespace;
void mynamespace::myfun(string str) 
{
    cout<<str<<endl;
}
//構造函數 //設置成員數據初始化值
Student::Student():name("student"),age(default_age)  
{
    cout<<"無參基類構造函數:"+name<<endl;
}
//構造函數
Student::Student(string name,int age)
{
    this->name=name;
    this->age = age;
    cout<<"有參基類構造函數:"+name<<endl;
}
//構造函數
Student::Student(int age)
{
    this->age = age;
    name="student";
    cout<<"有參基類構造函數:"+name<<endl;
}
//複製構造函數
Student::Student(const Student& another)
{
    name=another.name;
    age=another.age;
    cout<<"基類複製構造函數:"+name<<endl;
}
//賦值構造函數
Student& Student::operator=(const Student& another)
{
    //自賦值檢測
    if (this==&another)
    {
        return *this;
    }
    //釋放this原內存
    //賦值新內存
    name = another.name;
    age=another.age;
    cout<<"基類賦值構造函數:"+name<<endl;
    return *this;
}

//運算符重載
Student Student::operator+(const Student& another) const
{
    Student student;
    student.setname(name+" and "+another.name+"'s group");
    student.setage((age+another.age)/2);
    cout<<"基類加法運算符重載"<<endl;
    return student;
}
//運算符重載
Student Student::operator+(const string& anothername) const
{
    Student parents(anothername);
    cout<<"基類加字符串運算符重載"<<endl;
    return parents;   //不能返回局部對象的引用。  返回對象,會將局部對象賦值給接收對象,再銷燬局部對象。不銷燬指針內存。返回引用,將局部引用賦值給接收引用,再銷燬局部對象,則接收引用的內容也全部銷燬了。
}
void Student::setname(string name)   //無需重複使用virtual
{
    this->name=name;   //this作爲對象Student
    cout<<"基類設置名稱參數:"+name<<endl;
}
string Student::getname() const
{
    cout<<"基類讀取名稱參數:"+name<<endl;
    return (*this).name;  //this是指針  可以取指向值
    //return name;
}
void Student::setage(int age)
{
    cout<<"基類設置年齡參數"<<endl;
    this->age=age;
}
int Student::getage()
{
    cout<<"基類共享靜態函數讀取年齡參數"<<endl;
    return default_age;   //靜態函數只能操作靜態數據
}
//析構函數   所以堆棧指針在函數退出時總是會自動釋放指向的堆中的內存。造成原內存損壞(調用函數)
Student::~Student()
{
    cout<<"基類析構函數:"+name<<endl;
    //這裏填寫釋放對象內存的函數
}

//嵌套類函數定義
string Student::sex::getsex()
{
    return sexstr;
}
//嵌套類函數定義
void Student::sex::setsex(allsex sextype)
{
    if (sextype==boy)
        sexstr = "boy";
    else
        sexstr = "girl";
}


//在類模板外部定義成員函數的方法爲:template<模板形參列表> 函數返回類型 類名<模板形參名>::函數名(參數列表){函數體},
template<class TT> TT classA<TT>::add(TT tt,TT pp){ 
    return tt+pp;
}               


main.cpp文件主要涉及頭文件引用、空間引用、結構體、類型別名、常值變量、全局變量、常值函數、函數別名、函數指針、函數聲明、函數參數、內聯函數、模板函數、時間函數、輸入輸出流、字符串轉換、變量推導、類的指針和數組、lambda表達式、智能指針、類型向上轉型、輸入輸出文件流、STL容器和算法操作、數組、向量、列表、堆棧、隊列、集合、映射、迭代器、搜索算法、分區算法、排序算法、操作算法、字符串正則表達式、多線程、線程安全、自定義字面量、變長模板等內容

主文件main.cpp文件

#pragma once                  //防止文件被多重包含
#include <stdio.h>
#include <stdlib.h>
#include <chrono>             //正則表達式   vs2012後有
#include <iostream>           //數據流
#include <memory>             //內存操作
#include <fstream>            //文件流
#include <string>             //字符串
#include <regex>              //正則表達式
#include <exception>          //異常
#include <stdexcept>          //異常類型
#include <iterator>           //迭代器
#include <array>              //可獲取大小的固定數組
#include <vector>             //數據結構  連續分佈的動態數組
#include <list>               //不連續分佈的雙向鏈表
#include <deque>              //雙頭隊列
#include <queue>              //先入先出隊列
#include <stack>              //先入後出堆
#include <set>                //有序集合
#include <map>                //哈希表
#include <algorithm>          //STL算法
#include <numeric>            //數值計算算法
#include <math.h>             //數值計算算法
#include <functional>         //函數指針,將函數指針作爲自定義函數參數   實現設置回調函數
#include <thread>             //多線程庫   vs2012後有
#include <atomic>             //原子類型  線程安全  vs2012後有
#include <mutex>              //互斥體類型  vs2012後有
#include <time.h>             //時間類型
#include "namespace.h"        //自定義空間  ""先搜索本地目錄  再遍歷全部  <>遍歷系統目錄     引用h文件  相當於h文件直接展開

using namespace std;                                                    //重用空間函數
using namespace mynamespace;                                            //自定義命名空間   要避免不同空間下的同名變量函數衝突
struct People                                                           //自定義結構體
{
    string name;
    int age;
}People1;                                                               //People是類型,People1是變量
typedef int* intptr;                                                    //類型別名  typedef爲已有類型聲明提供一個新的名稱  using有類似功能
const string studentname = "student";                                   //常量變量  任何不再名稱空間、函數、類中的名稱都被認爲全局作用
string stringtemp="";                                                   //全局變量
const int getstudentnumber(){return 33;}                                //常量表達式
typedef void (*funtype)(string);                                        //定義函數指針類型  輸入string  返回void    等價於 using funtype = void (*)(string);。爲了出現頻率高的代碼,避免改動繁瑣性和書寫繁瑣性
//function<void(string)> function_pointer = printstring;                //函數指針
//void (*function_pointer)(string str)= printstring;                    //函數指針
void printstring(string str);                                           //函數聲明
void process(const vector<string>& vec,function<void(string)> fun);     //函數聲明
inline void sprintf1(string str){                                       //內聯函數,編譯時在代碼處展開,爲讀使用頻率高,且代碼量小的函數。避免改動繁瑣型和調用快捷性
    cout<<str<<endl;
}
void printstring(string str)                                            //自定義函數(打印輸出字符串)
{
    cout<<str<<endl;
}
void process(const vector<string>& vec,function<void(string)> fun)      //自定義函數(調用函數fun,調用向量成員)
{
    for (auto& item:vec)
        fun(item);
}
template<class T> void print(T a)                                       //模板函數,函數模板通式
{
    cout<<a<<endl;
}
string Student::default_name = studentname;                             //類內靜態變量,無需創建對象,初始化需放在函數外全局區域
int main()
{
    myfun("代碼調試者:欒鵬");                                          //調用自定義空間內函數,//兩個字符串常量不能相加
    cout<<"============基本類型數據============"<<endl;                   //cout<<    <<endl打印輸出
    timenow = time(NULL);                                               //空間靜態變量,直接使用,此句返回的只是一個時間戳
    cout<<"當前時間戳"<<timenow<<"\n";                                   //時間戳表示指定時間點距離標準時間原點之間的秒數
    int* const temp = new int(0);                                       //const作用於左側的類型(作用於*指針),此處表示指向不變,若作用於int(const int*  var),表示指向的數據不變
    int& studentnumber = *temp;                                         //設置引用,引用不佔內存,不創建對象,只是別名
    cout<<"默認學生名稱爲"+studentname+"\n";                           //cout中支持轉移字符,支持打印各種類型數據
    cout<<"默認班級人數爲"<<(studentnumber = getstudentnumber())<<endl; //打印輸出,常量變量、調用常量表達式,endl是換行刷新

    string str1 = to_string(std::min(studentnumber,22));                //其他類型轉化爲字符串。min和max被vs中windows.h定義爲了宏,導致庫裏面的正常函數沒法使用:
    string str2 = str1+"34";                                            //字符串使用+合併,字符串不能直接初始化爲兩個常量字符串相加。如果不能string str2 = "11"+"34";    
    studentnumber = (stoi(str2))/10;                                   //字符串轉化爲指定進制的其他類型,stoi,stof,stod
    cout <<"算上班主任,班級人數:"<<studentnumber;
    cout.flush();                                                       //顯示刷新數據流,寫入控制檯,不換行
    //float classtime = 45_min+50_s;                                    //調用自定義字面量,c++11後纔有
    classA<int> initstr;                                                //定義模板類 <>內替換成需要的類型,                
    auto  int1=initstr.plus(3,2);                                       //自動變量類型,會去除const限定符和引用 
    decltype(int1) int2=0x11;                                           //類型借用,0x爲16進製表示
    int int3=int1^int2;                                                 //補碼按位異或   即101與10001  按位異或爲10100
    cout<<";其中男孩個數約"<<int3<<endl;                               //打印輸出

    classA<> initstr1;                                                  //使用默認類型參數

                                                                        //棧stack跟隨函數,一個函數,一個堆棧,相互不影響,自動釋放,一級緩存,先進後出,內存限定  內存向下增長
                                                                        //堆heap,公共空間  手動釋放,二級緩存存儲,鏈表結構,內存根據物理內存,內存向上增長。
                                                                        //全局區、文字常量區、程序代碼區   字符指針初始化的字符串在常量,指針在棧上
    cout<<"============類的指針與數組============"<<endl;
    Student* student=nullptr;                                           //指針定義初始化爲空
    student = new Student;                                              //開闢指針內存   指針存在棧中  對象在堆中
    //student->age = 3;                                                 //私有成員  無法訪問
    //(*student).name = "小明";                                           //保護成員   無法訪問
    student->setname("小明");
    delete student;                                                     //釋放指針內存
    student = nullptr;                                                  //指針置空   防止野指針
    Student* students=nullptr;                                          //類指針定義,初始化爲空
    students = new Student[3];                                          //開闢數組內存
    delete[] students;                                                  //釋放數組內存

    string namestr;
    int age;
    print("輸入學生姓名和年齡:");                                        //調用模板函數
    cin>>namestr>>age;                                                  //獲取從窗口輸入的數據,分別放在namestr變量和age變量中
    auto vlambda = [namestr](int age){                                  //lambda表達式,函數名代替函數體展開  []內爲捕獲變量  ()內爲參數,在沒有參數時可以不加()
        cout<<"創建學生結構體:名稱:"+namestr<<";年齡:"<<age<<endl;
    };  
    vlambda(age);                                                       //展開vlambda函數




    cout<<"============學生,基類操作============"<<endl;
    Student student1("曉剛");                                         //在堆棧中創建對象
    student1.setname("小剛");                                         //調用類內函數,在棧上使用對象
    Student* student2 = new Student("曉紅",7);                            //使用new 開闢的內存在堆上,指針在棧上,需要代碼釋放在堆上的對象
    student2->setname("小紅");                                            //在堆上使用對象
    Student student3(student1);                                         //調用複製構造函數,即複製一個對象,
    Student& student4 = student3;                                       //設置引用,引用不創建對象,只是別名
    student4 = *student2;                                               //賦值構造函數
    student4.setname("小劉");
    Student student5 = student1+student4;                               //重載加法運算符
    student5 = student3+"小韓";                                           //重載加法運算符
    cout<<"學生列表:"+student1.getname()
        <<+"、"+student2->getname()
        <<"、"+student3.getname()
        <<"、"+student4.getname()
        <<"、"+student5.getname()<<endl;
    delete student2;                                                    //釋放內存,會調用析構函數。只有通過new開闢了內存的才需要釋放,否則會自動釋放
    student2 = nullptr;                                                 //指針置空,避免野指針
    auto student6 = unique_ptr<Student>();                              //使用智能指針,指針銷燬時會自動銷燬指向內存,在try catch中不用擔心出錯而指針內存泄漏





    cout<<"============班長派生類操作============"<<endl;
    Monitor monitor;                                                    //生成派生類,會先調用基類構造函數,再調用派生類構造函數
    Student student11 = monitor;                                        //派生類轉化爲基類,產生截斷,這裏調用的是基類的構造函數
    //指向派生類對象的基類指針,可以調用派生類重寫的虛函數、基類中的非虛函數、基類的默認參數、基類中未被重寫的虛函數(被派生類繼承默認了)
    Student& student12 = monitor;                                       //引用指向派生類對象,派生類轉爲基類,不產生截斷。引用定義時需要初始化,引用不可改變
    student12.setname("小明");                                            //調用派生類重寫的虛函數
    student12.getname();                                                //調用基類函數
    student12.getage();                                                 //靜態函數,所有對象共享
    Student::getage();                                                  //靜態函數,可通過類型名稱調用
    monitor.getname("王");                                               //調用派生類的新增函數
    monitor.getname();                                                  //調用派生類包含的基類函數,不包含沒法調用
    monitor.setage();                                                   //調用派生類覆蓋的函數
    monitor.getage();                                                   //





    cout<<"============老師類型操作============"<<endl;
    Teacher* teacher = nullptr;                                         //抽象類不能實例化對象,但是可以建立指針                                                   
    teacher = new Headmaster();                                         //抽象類的子類可以實例化對象   因爲子類重寫了所有純虛函數,使得子類成爲非抽象類
    teacher->getname();                                                 //指針可以調用基類的方法,因爲存在聲明  但是實現方法是不一定   因爲不同派生類寫入方法不同
    delete teacher;                                                     //基類指針
    Headmaster Headmaster1("劉家航班主任");                               





    cout<<"============流操作============"<<endl;

    ifstream infile("input.txt", std::ios::in);                                     //輸入文件流ifstream  輸出文件流  ofstream   fstream雙向文件流同時讀寫文件
    ofstream outfile("output.txt",ios_base::trunc);                     //app寫之前移動到文件尾,ate打開後移動到文件尾,binary二進制模式輸入輸出
                                                                        //in從頭開始讀   out從頭開始寫   trunc打開刪除已有數據
    if (outfile && infile)
    {
        try                                                             //try{}catch(){}  嘗試運行某段代碼
        {
            infile.tie(&outfile);                                       //將輸入流與輸出流綁定,輸入流會自動刷新至輸出流,兩個輸出流也可以綁定,實現同步
            string readstr;
            infile>>readstr;                                            //讀入數據流  數據流同時進入輸出流
            outfile<<readstr;                                           //再一次寫入字符串
            ios_base::streampos curpos = outfile.tellp();               //獲取標記位置,輸出流tellp,輸入流tellg
            if (10==curpos)                                             //這裏等號兩邊緩過來會報錯
            {
                                                                        //輸出流seekp,輸入流seekg //iso_base::end流的結尾,iso_base::beg流的開始,iso_base::cur流的當前位置
                outfile.seekp(-2,ios_base::end);                        //-2表示指定流位置前面2個位置
                outfile<<0;
                outfile.close();
            }

            char line[1024]={0};                                        //按行讀取文件
            while(infile.getline(line, sizeof(line))) 
            {
            }
        }
        catch (const exception err)                                     //拋出異常並不一定遵循異常列表,java只能拋出異常列表中的異常
        {                                                               //c++中的所有異常都是exception的派生  所以拋出exception 沒有針對性
            cout<<"異常描述:"<<err.what()<<endl;                        //所有異常類都有.what(),異常描述函數
        }
        catch (...)                                                     //匹配所有異常          
        {                                                               //try catch 中異常類不需要字符串設置構造函數 throw需要字符串設置異常類的構造函數
            throw invalid_argument("無法打開文件");                     //拋出invalid_argumenty異常  除exception的所有異常類都需要字符串設置構造函數
        }
    }else
        cout<<"文件不存在"<<endl;





    cout<<"============STL容器和算法操作============"<<endl;            //STL  4類16大容器
                                                                        //順序容器  vector、deque、list、forward_list、array
                                                                        //關聯容器map、multimap、set、multiset
                                                                        //無序關聯容器或哈希表 unordered_map、 unordered_multimap、unordered_set、unordered_multiset
                                                                        //容器適配器  queue、priority_queue、stack
    //容器:一定數據結構的數據集;分配器:數據元素的內存管理;元素迭代器iterator:容器元素的訪問(指向元素的指針);算法:數據運算
    array<string,3> allstr0 = {"name1","name2","name3"};                //可獲取大小的固定數組
    vector<string> allstr1=vector<string>(10);                                              //連續分佈的動態數組
    list<string> allstr2;                                               //不連續分佈的雙向鏈表
    deque<string> allstr3;                                              //連續分佈的雙頭隊列
    queue<string> allstr4;                                              //先入先出的隊列
    stack<string> allstr5;                                              //先入後出的棧
    set<string>  allstr6;                                               //有序的元素唯一的集合
    multiset<string> allstr7;                                           //有序的元素不唯一的集合
    map<string,int>   map_student;                                      //multimap支持重複鍵值
    map_student.insert(pair<string,int>("小明",12));                  //map的插入

    string allnamestr[]={"小明","小王","小剛","小紅","小劉"};
    vector<string> allstudent(allnamestr, allnamestr+5);                //數組轉化爲向量
    //allstudent.assign(5,"studentname");                               //動態分配內存
    vector<string> allteacher(2);                                       //定義字符串向量;
    allteacher[0]="王老師";
    allteacher[1]="張老師";
    if (allstudent!=allteacher)                                         //向量==或!=進行了重載
    {
        allstudent.push_back("小張");                                 //尾部添加元素
        allstudent.pop_back();                                          //尾部刪除元素
        auto iter = begin(allstudent);                                  //獲取首部
        allstudent.insert(iter,"小李");                                   //在指定位置插入元素
        iter++;                                                         //相當於指針++
        *iter = "小陳";
        allstudent.erase(iter);                                         //在指定位置刪除元素  刪除後iter不能繼續使用了
        for (vector<string>::iterator iter1 = begin(allstudent);iter1!=end(allstudent);++iter1)
        {
            cout<<*iter1<<endl;
        }
        for (const auto& iter2:allteacher)                              //迭代器引用,反向迭代器rbegin(vectorstr1),insert_iterator插入迭代器,move_iterator移動迭代器
        {
            cout<<iter2<<endl;
        }
    }
    process(allstudent,[](string str){cout<<str<<endl;});               //使用lambda設置遍歷的回調函數
    process(allteacher,printstring);                                    //自定義函數作爲參數傳遞

    int sum=0;
    vector<int> vectorint1(10,1);
    auto it = find_if_not(begin(vectorint1),end(vectorint1),[](int i){return i<8;});    //搜索算法
    for_each(begin(vectorint1),end(vectorint1),[&sum](int i){sum+=i;});                 //操作算法,每個元素執行回調函數
    partition(begin(vectorint1),end(vectorint1),[](int i){return i%2;});                //分區算法  一個目標到兩個目標  通過返回值 true、false決定區間//lambda表達式,返回true的排在前面   返回false的排在後面
    std::sort(begin(vectorint1),end(vectorint1));                                           //排序算法,只能用於順序容器




    cout<<"============字符串和正則法則==========="<<endl;  
    string strtemp="luanpengluanpeng";
    string str11(strtemp,2,3);                                                          //構造函數,原字符串,起始位置,截取長度。從後向前依次可以省略。string str2(num,c);生成num個c字符的字符串
    string str= "luanpengluanpeng";
    str.swap(strtemp);  //交換字符串的值,
    //append和push_back在尾部添加字符串,
    //insert在指定位置插入字符串,
    //erase(在指定位置刪除長度字符串,
    //replace替換字符串,size和length返回長度,
    //substr子字符串,
    //find,返回的string::size_type 類型的值,string::npos表示字符串末尾後,查詢結束位置
    regex myregex("ua[l-q]");                                                           //正則表達式模式   //正則表達式   ^$\.*+?()[]{}|爲特殊字符
    regex_match(str,myregex);                                                           //驗證源字符串是否存在指定模式的子字符串
    smatch mysmatch;                                                                    //結果集  字符串數組
    if(regex_search(str,mysmatch,myregex))                                              //查找符合規則的字符串,默認只查詢第一個符合條件的   返回存在或不存在bool
    {
        for (auto x=mysmatch.begin();x!=mysmatch.end();x++) 
            cout<<x->str()<<endl;
    }                                               
    //$1表示匹配出的字符串第一段模糊區間  $&表示匹配出來的所有字符串  $表示匹配出來段前的字符串   $`表示匹配出來的斷後的字符串
    const string format("name=$1");                                                        //替換格式  替換成name=匹配出來的模糊字符串  
    string result=regex_replace(str,myregex,format);                                    //字符串替換
    cout<<result<<endl;




    thread t1(printstring,"這是一個新線程");                                           //創建多線程  可以有多個參數
    //t1.join;                                                                          //順序執行線程
    t1.detach();                                                                        //創建線程分支


    //如果使用較爲頻繁的對象構造,可以使用對象池   一次構造函數,每次去讀取即可
    //內存常見錯誤
    //內存泄漏,釋放操作不匹配,多次釋放,釋放未分配的,釋放堆棧內存
    //訪問無效內存,訪問已釋放內存,內存越界,指針未初始化
    system("pause");

}




//自定義字面量可以讓用戶定義符號所引起的變化   以_開頭   定義
//標準中 i  il   if被字面量爲創建複數complex<double>  complex<long double>   complex<float>
//float operator"" _min(float minute)
//{
//  return minute/60;
//}
//float operator"" _s(float second)
//{
//  return second/60/60;
//}


//只在c++11編譯器以後
//通過重載邊界條件
//double sum2(){
//  return 0;
//}
////變長模板
//template<typename T1,typename...T2> double sum2(T1 p,T2...args)
//{
//  double ret = p+sum2(args);
//  return ret;
//}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章