• C++基础03 const关键字、static关键字、拷贝构造函数、运算符重载、输入输出流的重载、异常处理、IO流


    一、const关键字

    const关键字修饰的代表是常量,只读,不可以修改,同时要求const对象必须初始化
    
    • 1
    
    #include "iostream"
    using namespace std;
    
    class Base{
    //    修饰成员函数 表示这个函数只能调用const类型函数 并且在函数中不可以修改任何成员变量
        void fucntion1() const;
    };
    
    class Person{
        int age;
        const string name;
    //    const修饰的成员变量只能通过初始化列表来构造
        Person(int age,string name):name(name){
            this->age=age;
        }
    };
    int main(){
    //    const定义常量
        const double min=9.9;
    
    //    修饰指针
        const int *p1;  // 靠int 比较近 所有指针p1 指向的值不可以修改
    //    *p1=100;
    
        int const *p2;  // 靠p2 比较近 所有指针p1 指向的值不可以修改
    //    *p2=13;
    
        int i=10;
        int * const p3=&i; // const靠近p3的位置,所以p3指向的地址不能变但是值可以变
    
        const int * const p4=&i; // p4指向的值和地址都不能变
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    二、static关键字

    #include "iostream"
    using namespace std;
    
    /*
     * static 关键字
     * 静态变量的特点就是,当一个函数返回后,下一次调用的时候该变量会保持上次的值
     * 函数内部的静态变量值开辟一次空间,并且不会因为多次调用产生副本,也不会因为函数返回而生效
     *
     * 可以用于解决同一个类的不同对象的数据共享
     *
     * 使用类名::标识符的方式访问静态数据成员,因为静态数据成员不属于任何一个对象,修改的话,需要加类型
     * 对静态成员初始化要定义在类定义外进行
     *
     * 静态成员函数主要用于处理该类的静态数据成员,可以直接调用静态数据成员
     * 如果要访问非静态成员则需要对象来访问
     * 使用 类名::函数名 操作符来调用静态成员函数
     * 使用 类.函数名 调用
     */
    
    class Person{
    private:
        int age;
        static int score;
    public:
        static void findPerson(Person perosn);
        Person(int age){
            this->age=age;
        }
        int getVisitors(){
            static int count = 0;
            return count++;
        }
    };
    int Person::score=10;
    
    void Person::findPerson(Person perosn) {
        cout << "age:" << perosn.age << endl;
    }
    int main(){
        Person person1(18);
        cout << person1.getVisitors() <<endl;
        Person person2(18);
        cout << person2.getVisitors() <<endl;
    
        Person::findPerson(person1);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    三、拷贝构造函数

    在创建对象时,是使用之前创建的对象来初始化新创建的对象
    如果类带有指针,并且动态内存分配,则必须有一个拷贝构造函数
    
    如果在类中没有定义拷贝构造函数,编译器会自行定义一个
    也可以自己写一个拷贝构造函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    //
    // Created by KerwinWan on 2023/4/20.
    //
    #include 
    #include "iostream"
    using namespace std;
    
    class Student{
    private:
        int age;
        char *name;
    public:
        void display(){
            cout << "age:" << age << " name:" << name << endl;
        }
        Student(char *n,int a){
            cout << "函数执行了" <<endl;
            age=a;
            name=n;
        }
    
        ~Student(){
            cout << "析构函数执行了" << endl;
            if (name!= nullptr){
                delete [] name;
                name=NULL;
            }
        }
    //    自定义拷贝构造
        Student(const Student&s){
            cout << "自定义拷贝构造函数执行" << endl;
            age=s.age;
            int len=sizeof(s.name);
            name=new char[len+1];
            strcpy(name,s.name);
            name[len]='\0';
        }
    };
    
    int main(){
        Student s1("zwj1",20);
        s1.display();
        Student s2(s1);
        s2.display();
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    四、运算符重载

    //
    // Created by KerwinWan on 2023/4/24.
    //
    #include 
    #include "iostream"
    using namespace std;
    /*
     * 运算符的重载 双目运算符重载
     * 运算符重载是重载系统内部的运算符函数,是实现静态多态性的方式之一,本质是函数重载
     *
     * 要求:不允许创造新的运算符,只能对已有的运算符重载
     * 不允许重载运算符有:成员运算符. 成员指针访问运算符.* 域运算符:: 求字节运算符sizeof 条件运算符?
     * 重载不能改变运算符运算对象的个数,比如+需要两个参数,不能只写一个参数
     * 重载不能改变运算符的优先级
     * 重载不能改变运算符的结合性
     * 重载的运算符必须和用户定义的自定义类型的对象一起使用,参数至少有一个类对象或引用
     */
    
    class Complex{
    private:
        int a;
        int b;
    public:
        Complex(int a,int b){
            this->a=a;
            this->b=b;
        }
        void display(){
            cout << "a:" <<a << " b:" << b << endl;
        }
    
        Complex& operator+=(const Complex another){
            this->a+=another.a;
            this->b+=another.b;
            return *this;
        }
    // 单目运算符重载
        int operator++(){
    
            return this->a+100;
        }
    };
    int main(){
        Complex c1(2,3);
        Complex c2(5,6);
        (c1+=c2).display();
        Complex c3(11,22);
        
        // 单目运算符重载后使用
        cout << c3.operator++() << endl;
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    五、输入输出流的重载

    class Complex{
    private:
        int a;
        int b;
    public:
        Complex(int a,int b){
            this->a=a;
            this->b=b;
        }
        void display(){
            cout << "a:" <<a << " b:" << b << endl;
        }
    
        Complex& operator+=(const Complex another){
            this->a+=another.a;
            this->b+=another.b;
            return *this;
        }
    // 单目运算符重载
        int operator++(){
    
            return this->a+100;
        }
     /*
     * 用户自己定义的类型的数据,是不可以直接用<<和>>来输入输出的,如果想想用这个来输入和输出自己定义的类型和数据 则必须要重载
     * cin 类型 istream类的对象
     * cout类型 ostream类的对象
     * 流运算符 >> <<
     * 必须采用友元函数的形式重载的原因
     * 1、这样就可以不创建对象直接调用函数
     * 2、输入输出流重载,不是类的成员,所以应该声明为类的友元函数
    
     * 构造参数
     * istream & operator >> (istream &,自定义类 &)
     * ostream & operator << (ostream &,自定义类 &)
    
     */
        friend ostream & operator<<(ostream &os,Complex &c);
        friend istream & operator>>(istream &is,Complex &c);
    
    };
    ostream & operator<<(ostream &os,Complex &c){
        cout << "自定义<<:" << endl;
        c.display();
        return os;
    }
    istream & operator>>(istream &is,Complex &c){
        cout << "请输入" <<endl;
        cin >> c.a >> c.b ;
        return is;
    }
    
    int main(){
        Complex c1(2,3);
        Complex c2(5,6);
        (c1+=c2).display();
        Complex c3(11,22);
    
        // 单目运算符重载后使用
        cout << c3.operator++() << endl;
    
        cin>>c1;
        cout<<c1;
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    六、异常处理

    
    #include 
    #include "iostream"
    using namespace std;
    
    /*
     * 程序运行的时候会出现异常
     * C++通过throw和try...catch进行异常处理
     * throw 语法如下 throw xxx      xxx为任何类型对象
     *
     * 还可以自定义异常对象
     * */
    class MyException{
    private:
        string message;
    public:
        MyException(string message){
            this->message=message;
        }
        string getstring(){
            return message;
        }
    };
    void FunDiv(int a,int b){
        if (b==0){
            throw "除数不能为0";
        } else if(b==1){
            throw MyException("nonono");
        }
        cout << "is OK" << endl;
        int c=a/b;
    }
    int main(){
        try {
            FunDiv(1,1);
        }catch (char const* a){
            cout << a <<endl;
        }catch (int a){
            cout << a <<endl;
        }catch (double a){
            cout << a <<endl;
        } catch (MyException myException) {
            cout << myException.getstring() <<endl;
        }
    
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    七、IO流

    
    #include 
    #include "iostream"
    #include "fstream"
    using namespace std;
    /*
     * 文件流的使用步骤
     * 1、定义一个文件流对象,输出文件流对象和输入文件流对象,输入输出针对内存而言
     * 2、使用文件流对象的成员函数打开一个磁盘文件,是的文件对象和磁盘文件之间建立连接
     * 3、使用提取和插入运算符对文件机械能读写,或使用成员函数进行读写
     * 4、关闭文件
    
     * 文件常见的打开方式
     * 1、in 以读的方式打开文件
     * 2、out以写的方式打开文件
     * 3、binary以二进制的方式对文件进行操作
     * 4、ate输出位置从文件的末尾开始
     * 5、app以追加的方式对文件进行写入
     * 6、trunc将文件内容清空再打开文件
     *
     * ifstream 用于从文件中读取 由istream派生而来
    
     * ofstream 用于将内容写到文件中 由ostream派生而来
     * */
    
    
    int main(){
    //    ifstream 对象名(文件路径,打开方式)
    //    ifstream file1("name.text",ios::in);
        ifstream fin;
        fin.open("/name.txt",ios::in);
    //    seekg方法 找相对位置  参数为 偏移量和位置指示 
    //    ios_base::beg 文件的开始位置 
    //    ios_base::cur 当前位置 
    //    ios_base::end 文件结尾
        fin.seekg(2,ios_base::beg);
        char buffer[256];
    //    第一个参数 读到哪里,第二个是读多少个
        while (fin.getline(buffer,256)) {
            cout << buffer << endl;
        }
    
    //  方式二
        ofstream fout;
        fout.open("/name.txt",ios::out);
        fout << "hello1111111111111afafaffasfsa1111111"<<endl;
    
        fin.close();
        fout.close();
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
  • 相关阅读:
    MySQL-日志
    第五节 Electron 模块介绍 remote模块详细介绍
    面对密集型的I/O任务处理,python该如何提高执行效率
    2-5基础配置-Win2003增加攻击面
    如何将带GPS的网络化的软件定义无线电接收机应用于分布式和移动频谱监测?(二)
    推荐收藏!商汤智能座舱算法岗面试题7道(含解析)!
    卷积神经网络文本分析,一文读懂卷积神经网络
    密码学基础——加密与哈希,凯撒密码,对称加密与非对称加密以及Diffie-Hellman密码交换协议
    Elasticsearch核心概念解析:索引、文档与类型
    CMake使用心得
  • 原文地址:https://blog.csdn.net/Wantfly9951/article/details/130229685