• C++ 类和对象


    1. 访问权限

    • public :公共权限
    • protected:保护权限,子类可以访问
    • private:私有权限,仅仅自己可以访问

    2. struct 和class区别

    • 在C++中,struct和class唯一的区别在于默认的访问权限不同
    • struct默认权限为公共
    • class默认权限为私有

    3. 属性成员私有化

    • 优点1:将所有成员属性设置为私有,可以自己控制读写权限
    • 优点2:对于写权限,我们可以检测数据的有效性
    class Person
    {
    public:
        void setName(string name)
        {
            _name = name;
        }
        
        string getName()
        {
            return _name;
        }
        
        int getAge()
        {
            return _age;
        }
        
        void setLover(string lover)
        {
            _lover = lover;
        }
        
    private:
        string _name; // 可读 可写
        int _age; // 可读
        string _lover; // 可写
    };
    
    • 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

    4. 把.hpp(或称为.h)文件和.cpp文件抽出来

    创建Person类

      1. 创建.hpp文件
    #ifndef hanshu_hpp
    #define hanshu_hpp
    #pragma once
    using namespace std;
    #include 
    #include 
    
    class Person
    {
    public:
        void setName(string name);
        string getName();
        
        int getAge();
        void setLover(string lover);
        
    private:
        string _name; // 可读 可写
        int _age; // 可读
        string _lover; // 可写
    };
    #endif /* hanshu_hpp */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 2 创建.cpp文件
    #include "hanshu.hpp"
    #include 
    using namespace std;
    
    void Person::setName(string name)
    {
        _name = name;
    }
    
    string Person::getName()
    {
        return _name;
    }
    
    int Person::getAge()
    {
        return _age;
    }
    
    void Person::setLover(string lover)
    {
        _lover = lover;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    5. 对象的初始化和清理

    • 构造函数和析构函数
    class Cat
    {
    public:
        //一、构造函数
        /**
         1. 没有返回值, 不用写void
         2. 函数名 与类名相同
         3. 构造函数可以有参数,可以发生重载
         4.创建对象的时候,构造函数会被自动调用,而且只调用一次
         */
        Cat()
        {
            cout << "cat 构造函数调用" << endl;
        }
        
        //二、析构函数
        /**
         1. 没有返回值 不写void
         2.函数名和类名相同 在名称前加~
         3.析构函数不可以有参数,不可以发生重载
         4.对象在销毁前,会被自动调用,而且只调用一次
         */
        ~Cat()
        {
            cout << "cat 析构函数调用" << endl;
        }
    };
    
    • 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

    6. 有参、无参、拷贝 – 构造函数

    class Pig
    {
    public:
        Pig()
        {
            cout << "pig 无参构造函数" << endl;
        }
        
        Pig(int a)
        {
            _age = a;
            cout << "pig 有参构造函数" << endl;
        }
        
        Pig(const Pig &p)
        {
            _age = p._age;
            cout << "pig 拷贝构造函数" << endl;
        }
        
        ~Pig()
        {
            cout << "pig 析构函数" << endl;
        }
        
        int _age;
    };
    
    int main(int argc, const char * argv[]) {
        // 一、括号法
    //    Pig p;
    //    Pig p2(10);
    //    Pig p3(p);
        
    //    Pig p(); // 不要这样写
        // 注意事项1:
        // 1. 调用默认构造函数时候,不要加(),因为编译器会误认为是一个函数的声明
        
        // 二、显示法
        Pig p1;
        Pig p2 = Pig(10);
        Pig p3 = Pig(p2);
          
        Pig(10); // 匿名对象 特点:当前行执行结束后,系统会立即回收匿名对象
        // 注意事项2:
        // 2. 不要利用拷贝构造函数 初始化匿名对象
    //    Pig(p2); // 报错:Redefinition of 'p2' 因为 Pig(p2) 会被编译器转换为 Pig p2; 重复定义了对象
        
        // 三、隐式转换法
        Pig p4 = 10; // 会被转换为 Pig p4 = Pig(10);
        Pig p5 = 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
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    7. 拷贝构造函数调用时机

    • C++ 中拷贝构造函数调用时机通常有三种情况
      1. 使用一个已经创建完毕的对象来初始化一个新对象
      1. 值传递的方式给函数参数传值
      1. 以值方式返回局部对象
    int main(int argc, const char * argv[]) {
    //    1. 使用一个已经创建完毕的对象来初始化一个新对象
    //    Pig p1 = Pig(10);
    //    Pig p2 = p1;
        /** 打印内容
         pig 无参构造函数
         pig 拷贝构造函数
         pig 析构函数
         pig 析构函数
         */
        
        //2. 值传递的方式给函数参数传值
    //    Pig p3;
    //    eat(p3); // 值传递,内部会拷贝一份对象,所以会调用拷贝构造函数
        /** 打印内容
         pig 无参构造函数
         pig 拷贝构造函数
         pig 析构函数
         pig 析构函数
         */
        
        // 3. 以值方式返回局部对象
        Pig p = getPig();
        cout << "函数调用的地址:" << (int*)&p << endl;
        /** 打印内容(在Mac平台下,用xcode打印如下,但是原来教学视频在Windows下,打印的地址却不一样,会调用拷贝构造函数,所以严格意义来说,这个应该和平台有关系)
         pig 无参构造函数
         函数创建的地址:0x7ff7bfeff2d8
         函数调用的地址:0x7ff7bfeff2d8
         pig 析构函数
         */
        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

    8. 构造函数调用规则

    一、 默认情况下,C++编译器至少给一个类添加3个函数

      1. 默认构造函数(无参,函数体为空)
      1. 默认析构函数(无参,函数体为空)
      1. 默认拷贝构造函数,对属性进行值拷贝

    二、构造函数调用规则如下:

      1. 如果用户定义有参构造函数,C++不再提供默认无参构造,但是会提供默认拷贝构造
      1. 如果用户定义拷贝构造函数,C++不会再提供其他构造函数

    9.深拷贝和浅拷贝

    概念:

    • 深拷贝:重新开辟一块内存,指向新的地址
    • 浅拷贝:新的指针,指向原来的内存地址
    class Horse
    {
    public:
        Horse()
        {
            cout << "Horse 无参构造函数" << endl;
        }
        
        Horse(int age, int height)
        {
            _age = age;
            _height = new int(height);
            cout << "Horse 有参构造函数" << endl;
        }
        
        Horse(Horse &h)
        {
            _age = h._age;
            _height = new int(*h._height); // 通过new,开辟一块新的内存空间,深拷贝
    //        _height = h._height; // 指针的值引用,浅拷贝
            cout << "Horse 拷贝构造函数" << endl;
        }
        
        ~Horse()
        {
            delete _height; // 浅拷贝的时候,第二个对象是否这个指针引用的值的时候,会释放失败,崩溃,深拷贝则不会
            _height = NULL;
            cout << "Horse 析构函数" << endl;
        }
        
        int _age;
        int *_height;
    };
    
    int main(int argc, const char * argv[]) {
        
        Horse h1(3,5);
        Horse h2(h1);
        cout << "h1的年龄:" << h1._age << ",  h1的身高:" << *h1._height << endl;
        cout << "h2的年龄:" << h2._age << ",  h2的身高:" << *h2._height << 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
  • 相关阅读:
    FlinkSql中的join操作详解
    在antd里面渲染MarkDown并且自定义一个锚点目录TOC(重点解决导航目录不跟随文档滚动的问题)
    【华为OD机试】分苹果
    达梦 dameng 数据库之升级打怪数据库兼容问题记录(1)
    1014:与圆相关的计算
    VWware设置静态ip地址及不同网络模式讲解
    基于肤色模型(YCbCr模型)的人面定位统计算法,Matlab实现
    如何看待 30 岁学云计算,转行做云计算运维这件事?
    辅助驾驶功能开发-功能规范篇(24)-3-影子模式功能触发规范
    贝叶斯学习
  • 原文地址:https://blog.csdn.net/JH_Cao/article/details/126371957