• C++学习笔记03-类的默认成员函数


    1 类的默认6个成员函数

    如果定义了一个空类,其实不是空类,任何一个类都会有默认成员函数。
    自己定义了就用定义,不定义就用默认生成的。

    • 初始化 和 清理
      构造函数:完成初始化工作
      析构函数:完成清理工作

    • 赋值 和 拷贝
      拷贝构造函数:使用同类对象初始化创建对象
      运算符重载:一个对象与另一对象进行运算

    • 取地址重载
      普通对象
      const对象

    1.1 构造函数

    构造函数是特殊函数,实例化时,在生成相应对象时编译器会自动调用该函数,保证每个对象都有一个合适的初始化值,并且在对象生命周期里面只能调用一次。
    
    • 1

    构造函数的基本特征:

    • 函数名 与 类名 同名
    • 无返回值
    • 对象实例化时自动调用对应构造函数
    • 构造函数可以重载
    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
        Studet(const char *name, int age); //构造函数 
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
    };
    
    Studet::Studet(const char *name, int age) //构造函数 
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::SetStudetInfo(const char *name, int age) //方法
    {
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21);
        
        //s1.SetStudetInfo("李三", 20);
        s1.ShowStudetInfo();
        
        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

    构造函数 重载

    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
        Studet(const char *name, int age); //构造函数
        Studet(void); //构造函数 重载
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
    };
    
    Studet::Studet(const char *name, int age) //构造函数 
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, name);
        Age = age;
    }
    
    Studet::Studet(void) //构造函数 重载
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, "小白");
        Age = 18;
    }
    
    void Studet::SetStudetInfo(const char *name, int age) //方法
    {
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21), s2;
        
        //s1.SetStudetInfo("李三", 20);
        s1.ShowStudetInfo();
        s2.ShowStudetInfo();
        
        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

    ==重载构造函数 与 构造函数 合并 ==

    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
        Studet(const char *name, int age); //构造函数
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
    };
    
    Studet::Studet(const char *name = "小白", int age = 18) //缺省构造函数 
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::SetStudetInfo(const char *name, int age) //方法
    {
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21), s2;
        
        //s1.SetStudetInfo("李三", 20);
        s1.ShowStudetInfo();
        s2.ShowStudetInfo();
        
        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

    ==若不定义构造函数则是随机值,但对定义类型会初始化构造函数 ==

    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Time
    {
    public: //共有的
        Time(const char *name, int age) //构造函数
        {
            std::cout << "调用了Time构造函数" << std::endl;
            Year = 2022;
            Month = 10;
        }
    private: //私有的
        int Year; //属性
        int Month; //属性
    };
    
    class Studet
    {
    public: //共有的
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
        Time Tm;
    };
    
    • 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

    1.1.1 构造函数的初始化列表

    • 构造函数的初始化列表是真的初始化,在定义的时候初始化。
    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
    	Studet(char *name, int age); //构造函数 
        void SetStudetInfo(char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char* Name; //属性
        int Age; //属性
    };
    
    //采用初始化列表
    Studet::Studet(char* name, int age): Name(name), Age(age)
    {
    
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21);
    
        s1.ShowStudetInfo();
        
        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

    注意

    • const 必需在初始化列表中初始化
    • 引用必须初始化

    1.2 析构函数

    析构函数与构造函数相反,是用来清理对象。对象销毁时调用一次析构函数进行清理工作。
    
    • 1

    构造函数的基本特征:

    • 析函数名 是在 类名 前加~
    • 无返回值
    • 一个类有且只有一个析构函数,如果没有显示定义,系统会自动生成默认的析构函数
    • 对象声明结束时,编译器会自动调用析构函数
    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
        Studet(const char *name, int age); //构造函数
        ~Studet() //析构函数
        {
            std::cout << "调用了析构函数" << std::endl;
        }
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
    };
    
    Studet::Studet(const char *name = "小白", int age = 18) //缺省构造函数 
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::SetStudetInfo(const char *name, int age) //方法
    {
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21), s2;
        
        //s1.SetStudetInfo("李三", 20);
        s1.ShowStudetInfo();
        s2.ShowStudetInfo();
        
        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

    1.3 拷贝构造函数

    拷贝 + 构造函数,看名字就是知道意思了。
    **拷贝构造函数用于创建对象时,创建一个与一个对象一模一样的新对象。**
    
    • 1
    • 2

    拷贝构造函数的基本特征:

    • 拷贝构造函数是构造函数的一个重载形式
    • 拷贝构造函数只有一个,且必须使用引用传参,如果使用传值的方式传参,将会引起无穷递归调用。
    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
        Studet(const char *name, int age); //构造函数
        Studet(Studet &s); //构造函数 
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
    };
    
    Studet::Studet(const char *name, int age) //构造函数 
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, name);
        Age = age;
    }
    
    Studet::Studet(Studet &s) //拷贝构造函数 
    {
        std::cout << "调用了拷贝构造函数" << std::endl;
        strcpy(Name, s.Name);
        Age = s.Age;
    }
    
    void Studet::SetStudetInfo(const char *name, int age) //方法
    {
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21);
        Studet s2(s1);
        
        s1.ShowStudetInfo();
        s2.ShowStudetInfo();
        
        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

    注意

    • 只进行字节拷贝的叫浅拷贝。自己不创建拷贝构造函数,则调用默认生成拷贝构造函数也能实现。
    • 带指针(栈)的拷贝叫深拷贝。若用默认拷贝构造函数会出问题。

    1.4 运算符重载

    - 函数名:==operator== 接【需要重载的运算符符号】
    - 函数原型为:【返回值类型】【operator】【操作符】【参数列表】
    
    • 1
    • 2

    特别注意:

    • 连接符 必须是 已有的,不能自己去创造新的操作。
    • 重载操作符对的是自己定义类型。
    • 作为类成员的重载函数时,其形参看起来比操作数目少 1 个成员,因为一个默认的this指针
    • .*, ::, sizeof, ?:, ., 这五个运算符号不能重载。
    1.4.1 相等运算符重载
    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
        Studet(const char *name, int age); //构造函数
        Studet(Studet &s); //构造函数
        bool operator == (Studet &s); //运算符重载函数
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
    };
    
    Studet::Studet(const char *name, int age) //构造函数 
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, name);
        Age = age;
    }
    
    Studet::Studet(Studet &s) //拷贝构造函数 
    {
        std::cout << "调用了拷贝构造函数" << std::endl;
        strcpy(Name, s.Name);
        Age = s.Age;
    }
    
    bool Studet::operator == (Studet &s) //运算符重载函数
    {
        return Age == s.Age;
    }
    
    void Studet::SetStudetInfo(const char *name, int age) //方法
    {
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21);
        Studet s2(s1);
        
        s1.ShowStudetInfo();
        s2.ShowStudetInfo();
        
        if(s1 == s1)
        {
            std::cout << "调用了运算符重载函数" << std::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
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    1.4.2 赋值运算符重载
    #include 
    #include  //头文件,C++11可以不用加.h、*hxx
    
    using namespace std; //命名空间声明
    
    class Studet
    {
    public: //共有的
        Studet(const char *name, int age); //构造函数
        Studet(Studet &s); //构造函数
        Studet& operator = (Studet &s); //赋值运算符重载函数
        void SetStudetInfo(const char *name, int age); //方法
        void ShowStudetInfo(void);
        
    private: //私有的
        char Name[20]; //属性
        int Age; //属性
    };
    
    Studet::Studet(const char *name, int age) //构造函数 
    {
        std::cout << "调用了构造函数" << std::endl;
        strcpy(Name, name);
        Age = age;
    }
    
    Studet::Studet(Studet &s) //拷贝构造函数 
    {
        std::cout << "调用了拷贝构造函数" << std::endl;
        strcpy(Name, s.Name);
        Age = s.Age;
    }
    
    Studet& Studet::operator = (Studet &s) //赋值运算符重载函数
    {
    	strcpy(Name, s.Name);
    	Age = s.Age;
        
        return *this;
    }
    
    void Studet::SetStudetInfo(const char *name, int age) //方法
    {
        strcpy(Name, name);
        Age = age;
    }
    
    void Studet::ShowStudetInfo(void)
    {
        std::cout << Name << " " << Age << std::endl;
    }
    
    int main(void)
    {
        Studet s1("王二", 21);
        Studet s2("李三", 20);
        
        s1.ShowStudetInfo();
        s2.ShowStudetInfo();
        s2 = s1;
        s2.ShowStudetInfo();
    
        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

    注意: 赋值运算符重载函数类似拷贝构造函数,同样存在浅拷贝深拷贝问题

  • 相关阅读:
    获取地址和区块链切换
    Android中使用Java操作List集合的方法合集,包括判读是否有重复元素等
    MATLAB基础-MAT文件的读写操作
    ROS常见问题 | 虚拟机打开RVIZ闪退出错
    MySQL——统计函数count,合计函数sum,(avg,max,min)函数
    案例推荐|助力智慧城市,Pulsar Functions 的边缘物联网场景实践
    【目标检测】Fast R-CNN论文详细解读
    hadoop项目之求出每年二月的最高气温(Combiner优化)
    Windows11快捷键大集合+手动给程序添加快捷键
    11月22日:操作系统实验杂记(文本编辑器vim,查看文件内容cat命令,创建并使用Makefile文件,虚拟机共享文件夹)
  • 原文地址:https://blog.csdn.net/weixin_46672094/article/details/127839020