• C++中的类详解


    知识点1【封装】

    1. 把变量和函数合成一个整体,封装在一个类中
    2. 对变量和函数进行访问控制(公有、私有、保护)
    访问属性属性对象内部对象外部
    public公有可访问可访问
    protected保护可访问不可访问
    private私有可访问不可访问

    在没有涉及继承与派生时,protected与private 是同等级的,外部不允许访问。

    知识点2【类的初识】

    #include 
    #include
    using namespace std;
    class Person{
    private:
        char name[20];//定义类的时候,不要给成员初始化
        int age;
    public:
        void setNmae(char* n){
            strcpy(name,n);
        }
        char* getName(){
            return name;
        }
        void setAge(int a){
            age = a;
        }
        int getAge(){
            return age;
        }
    };
    
    int main(int argc, char *argv[])
    {
        Person person;
        char name[20] = "tony";
        person.setNmae(name);
        person.setAge(15);
        cout << person.getName() << person.getAge() << 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

    实例:设计一个点和圆的类

    #include 
    
    using namespace std;
    class Point{//设计一个点的类
    private:
        int m_x;
        int m_y;
    public:
        void setX(int x){
            m_x = x;
        }
        int getX(){
            return m_x;
        }
        void setY(int y){
            m_y = y;
        }
        int getY(){
            return m_y;
        }
    };
    
    class Circle{//设计一个圆的类
    private:
        Point point;
        int r;
    public:
        void setPoint(int x,int y){
            point.setX(x);
            point.setY(y);
        }
    
        void setR(int x){
            r = x;
        }
        void isPointOnCircle(Point &ob){
            //判断点与圆的关系
            int distance = (point.getX()-ob.getX()) *(point.getX()-ob.getX()) + (point.getY() - ob.getY()) * (point.getY() - ob.getY());
            if(distance > r*r){
                cout << "在圆外" << endl;
            }else if(distance == r*r){
                cout << "在圆上" << endl;
            }else{
                cout << "在圆内" << endl;
            }
        }
    
    };
    
    int main(int argc, char *argv[])
    {
    	//实例化一个点对象
        Point p1;
        p1.setX(5);
        p1.setY(5);
        
        //实例化一个圆对象
        Circle circle;
        circle.setR(3);
        circle.setPoint(3,3);
        //判断点point与圆的关系
        circle.isPointOnCircle(p1);
        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

    知识点3【类的空间大小】

    成员数据占类的空间大小,成员函数不占类空间的大小。

    using namespace std;
     class Data
     {
     private:
     //成员数据 占类的空间大小
     int num;//4B
     public:
    
     //成员函数 不占类的空间大小
     void setNum(int data)
     {
     num = data;
     }
     int getNum(void)
     {
     return num;
     }
     };
     void test01()
     {
     printf("%d\n",sizeof(Data));//4B
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    知识点4【在类内声明 类外定义 成员函数】

    class data{
    private:
        int num;
    public:
        void setNum(int x);
        int getNum();
    };
    
    void Data::setNum(int x){
         num = x;
     }
     
    int Data::getNum(){
         return num;
     }
    
    void test01(){
         Data data;
         data.setNum(100);
         cout << data.getNum() << endl;
     }
    int main(int argc, char *argv[]){
        test01();
        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

    知识点5【类的定义在头文件 成员函数 在cpp文件中实现】

    data1.h

    #ifndef DATA1_H
    #define DATA1_H
    
    
    class Data1
    {
    private:
        int num;
    public:
        void setNum(int x);
        int getNum();
    };
    
    #endif // DATA1_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    data1.cpp

    #include "data1.h"
    
    void Data1::setNum(int x){
        num = x;
    }
    
    int Data1::getNum(){
        return num;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    main.cpp

    #include 
    #include"data1.h"
    
    using namespace std;
    
    void test01(){
         Data1 data;
         data.setNum(1000);
         cout << data.getNum() << endl;
     }
    
    int main(int argc, char *argv[]){
        test01();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    知识点6【构造和析构函数的概述】

    构造函数和析构函数都会被编译器自动调用,构造函数完成对象的初始化动作,析构函数在对象结束的时候完成清理工作。

    注意:初始化和清理工作是编译器强制我们做的事情,即使程序并没有提供初始化操作和清理操作,编译器也会给程序增加默认的操作,但是默认操作并不会做任何事。

    构造函数:实例化对象的时候系统自动调用
    析构函数:对象释放的时候系统自动调用

    知识点7【构造和析构函数的定义】

    构造函数的语法:
    构造函数名与类名相同,没有返回类型,连void都不可以,但可以有参数,可以重载。
    析构函数的语法:
    析构函数的名字是在类名前面加“ ~ ”组成,没有返回类型,连void都不可以,不能有参数,不能重载。
    案例:

    #include 
    
    using namespace std;
    
    class Data
    {
    public:
        Data() {
            cout << "无参构造函数" << endl;
        }
    
        Data(int num){
            num = 100;
            cout << "有参构造函数" << endl;
        }
    
        ~Data(){
            cout << "析构函数" << endl;
        }
    };
    
    int main(int argc, char *argv[])
    {
        cout << "-----------01----------" << endl;
        Data ob;
        cout << "-----------02----------" << 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

    知识点8【构造函数的分类以及调用】

    1、构造函数的分类

    按参数类型分类: 分为无参构造函数和有参构造函数
    按类型分类:普通构造函数和拷贝构造函数(复制构造函数)

    2、构造函数的调用

    #include 
    
    using namespace std;
    
    class Data
    {
    private:
        int num;
    public:
        Data() {
            num = 0;
            cout << "无参构造函数" << endl;
        }
    
        Data(int num1){
            num = num1;
            cout << "有参构造函数" << num << endl;
        }
    
        ~Data(){
            cout << "析构函数" << num << endl;
        }
    };
    void test01(){
        //调用无参或默认构造函数
        Data ob;
        //调用有参构造函数(显式调用)
        Data ob1 = Data(100);
        //调用有参构造函数(隐式调用)
        Data ob2(1000);
        //隐式转换的方式 调用有参构造(针对于 只有一个数据成员)(尽量别用)
        Data ob3 = 10000;//转化成Data ob5(30)
    
        //匿名对象(当前语句结束 匿名对象立即释放)
        Data(40);
        cout << "---------------------" << endl;
    
        //千万不要 用以下方式调用 无参构造
        //Data ob4();//不会被认为时实例化对象,会被看作函数ob4的声明
    }
    
    int main(int argc, char *argv[])
    {
        cout << "-----------01----------" << endl;
        test01();
        cout << "-----------02----------" << 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

    在这里插入图片描述
    注意:在同一作用域,构造和析构的顺序相反(类似于栈,先进后出)

    3、拷贝构造函数(系统提供一个拷贝构造函数 赋值操作)

    #include 
    
    using namespace std;
    
    class Data
    {
    public:
        int num;
    public:
        Data() {
            num = 0;
            cout << "无参构造函数" << endl;
        }
    
        Data(int num1){
            num = num1;
            cout << "有参构造函数" << num << endl;
        }
    
        //拷贝构造函数
        Data(const Data &ob){//Data &ob = ob5;
            num = ob.num;
            cout << "拷贝构造函数" <<endl;
        }
    
        ~Data(){
            cout << "析构函数" << num << endl;
        }
    };
    void test01(){
    
        //调用有参构造函数(隐式调用)
         Data ob3 = Data(100);
         cout<<"ob3.num = "<<ob3.num<<endl;
    
        //显式调用拷贝构造函数
        Data ob5 = Data(ob3);
        cout<<"ob5.num = "<<ob5.num<<endl;
    
        //隐式调用拷贝构造函数
        Data ob6(ob3);
        cout<<"ob6.num = "<<ob6.num<<endl;
    
        //隐式转换调用拷贝构造函数
        Data ob7 = ob3;
        cout<<"ob6.num = "<<ob6.num<<endl;
    }
    
    int main(int argc, char *argv[])
    {
        cout << "-----------01----------" << endl;
        test01();
        cout << "-----------02----------" << 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

    记住一句话:旧对象初始化新对象才会调用拷贝构造函数

    Data ob1(10);
    Data ob2(ob1);//拷贝构造
    Data ob3 = Data(ob1);//拷贝构造
    Data ob4 = ob1;//拷贝构造函数
    
    • 1
    • 2
    • 3
    • 4

    注意:下方就不会调用拷贝构造

    Data ob1(10);
    Data ob2;
    ob2 = ob1;//不会调用拷贝构造 单纯对象 赋值操作
    
    • 1
    • 2
    • 3

    案例:

    void test02(){
         Data ob1 = Data(100);
         Data ob2;
         ob2 = ob1;
         cout<<"ob1.num = "<<ob1.num<<endl;
         cout<<"ob2.num = "<<ob2.num<<endl;
    
    
    
    }
    
    int main(int argc, char *argv[])
    {
        cout << "-----------01----------" << endl;
        test02();
        cout << "-----------02----------" << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    4、拷贝函数的注意事项

    (1)不能调用拷贝构造函数区初始化匿名对象
    (2) 对象作为函数的参数 如果实参与形参都是普通对象 那么就会调用拷贝构造
    (3)函数返回局部对象,在qt中会被优化,从而调用不了拷贝构造

    知识点9【构造函数的调用规则】

    系统默认会对任何一个类提供三个函数成员函数:
    默认构造函数(空) 默认析构函数(空) 默认拷贝构造函数(浅拷贝)
    1、如果用户提供了有参构造,将会屏蔽系统的默认构造函数
    2、如果用户提供了有参构造,不会屏蔽系统的默认拷贝构造函数
    3、如果用户提供了拷贝构造函数,将会屏蔽系统的默认构造函数和默认拷贝构造函数

  • 相关阅读:
    Elastic Stack--01--简介、安装
    多人访问同一个springboot项目会不会出现并发问题
    C++基础
    Vue3执行流程思路分析-流程图
    请体验一下falcon 180b 大语言模型的感觉
    C++教程从入门到实战
    18.2 使用NPCAP库抓取数据包
    FreeIPA 统一身份认证实现
    python解析word拆分Excel选择题格式(3、判断题)
    1、数据库-ACID理论
  • 原文地址:https://blog.csdn.net/DUANJIAWEIDUANJIAWEI/article/details/126201105