C++类和对象

文章详细介绍了C++中的类和对象,包括访问权限(public,protected,private),成员(属性和行为),构造函数(无参、有参、拷贝构造)和析构函数的作用,以及深拷贝和浅拷贝的概念。还涉及了静态成员变量和函数,对象成员,友元,运算符重载,以及面向对象的三大特性:封装、继承和多态。此外,文章还讲解了文件操作的基本概念和方式。
摘要由CSDN通过智能技术生成

十三、类和对象总览

  • 基础框架:

    • 类 class 类名

      • 包括:

        • 1.访问权限

          class默认权限为private 而struct默认权限为public

          • 公共权限 public:

            类内可以访问 类外不可以访问

          • 保护权限 protected:

            类内可以访问 类外不可以访问 子类可以访问

          • 隐私权限 private:

            类内可以访问 类外不可以访问 子类不可以访问

        • 成员

          • 2.属性(成员属性、成员变量)

          • 3.行为(成员函数、成员方法)(多用函数定义)

            • 创建一个类,C++默认创建:

              • 1.默认无参构造函数(空实现)

              • 2.析构函数(空实现)

              • 3.拷贝构造函数(值拷贝)

                也就是说拷贝构造函数默认就有,可以直接进行值拷贝

    • 对象 定义:类名 对象名;

      • 属性赋值 类名.对象名(不用写数据类型)

      • 行为 对象名.行为名

  • class和struct的区别:C++ class和struct到底有什么区别详解

  • 指向类的指针与->运算符

    • 定义一个指向类的指针,然后可以让此指针指向类中的对象

      Box Box1(3.3, 1.2, 1.5); ​ // Declare box1 ​Box Box2(8.5, 6.0, 2.0); ​ // Declare box2 ​Box *ptrBox; // Declare pointer to a class. ​ // 保存第一个对象的地址 ​ptrBox = &Box1; ​ // 现在尝试使用成员访问运算符来访问成员 ​cout << "Volume of Box1: " << ptrBox->Volume() << endl; ​ // 保存第二个对象的地址 ​ptrBox = &Box2; ​ // 现在尝试使用成员访问运算符来访问成员 ​cout << "Volume of Box2: " << ptrBox->Volume() << endl;

    • C++中箭头运算符->,相当于把解引用和成员访问符两个操作符结合在一起,换句话说,p->func()和(*p).func()所表示的意思一样。

  • 构造函数和析构函数

    • 构造函数

      • 性质

        • 1.创建对象时构造函数会自动调用且只调用一次

        • 2.没有返回值,不用写void

        • 3.函数名与类名相同 可以有参数,可以发生重载

      • 分类

        • 按参数:有参构造、无参构造

        • 按照类型

          • 普通构造

          • 拷贝构造

            • 定义格式:构造函数名( const 类名 &实例化个体 ){}

            • 性质:

              • 1.创建类时,构造函数默认添加,对属性进行值拷贝

              • 2.若用户定义有参构造函数,C++不在提供无参构造,但是会提供默认拷贝构造

              • 3.若用户定义拷贝构造函数,C++不再提供其他构造函数(包括默认构造函数)

            • 什么情况下会调用拷贝函数:

              • 1.普通的构造函数调用

              • 2.值传递的方法给函数形参赋值

                函数形参为对象

              • 3.以值方式返回局部对象

                以函数return的方式被返回

            • 深拷贝与浅拷贝

              • 定义

                • 浅拷贝: 简单的赋值操作

                  浅拷贝就是简单的等号 ​默认的拷贝构造函数就是浅拷贝

                  • 默认拷贝构造里的代码段:

                    Person类: int m_age; int * m_height; Person(const Person &p) { m_age = p.m_age ; m_height = p.height ; }

                    • 解释:

                      p2拷贝p1,当p2析构函数调用后,p2.m_height在堆区的指向内存就会被释放,而p1.m_height也指向那个内存,当p1的析构函数调用时,因为p1.m_height所指向的那块内存已经被清除,所以程序会崩溃

                • 深拷贝: 在堆区重新申请空间,进行拷贝操作

                  深拷贝是重新创建内存来进行拷贝

                  • 代码实现:

                    Person类: int m_age; int * m_height; Person(const Person &p) { m_age = p.m_age ; m_height = new int(m_height) ; ​}

                    • p1.m_height与p2.m_height指向的不是同一个内存

              • 如果属性有在堆区开辟的,一定要自己提供拷贝构造函数(深拷贝),防止浅拷贝带来的问题

      • 调用:

        • 1.括号法

          • Person p1; 默认构造函数

          • Person p1(10); 有参构造函数

          • Person p1(p2); 拷贝构造函数

        • 2.显示法

          • Person p1; 默认构造函数

          • Person p1 = Person(10); 有参构造函数

          • Person p1 = Person(p2); 拷贝构造函数

        • 3.隐式转换法

          • Person p1 = 10; 有参构造函数

          • Person p1 = p2; 拷贝构造函数

      • 初始化列表

        • 利用构造函数进行初始化列表

          • 构造函数头部: Person(形参):属性1(值),属性2(值), ...

    • 析构函数

      • 性质

        • 程序在对象被销毁前会自动调用析构,无须手动调用且只调用一次

        • 没有返回值,不用写void

        • 函数名是 ~类名

        • 不能有参数,因此无法发生重载

  • 子对象:类对象作为类成员(对象成员)

    • C++:类对象作为类成员 CSDN

    • CSDN中的补充:A类有属性m_n,m_a即是A类的实例化对象,又是B类的属性。b为B类的实例化对象,则可这样调用属性:b.m_a.m_n

  • 静态成员

    • 静态成员变量

      • 性质

        • 1. 静态成员变量被类中所有的对象共享,共用同一份数据

        • 2. 在编译阶段就分配内存,内存放在全局区

        • 3. 类内声明,类外初始化

          • 原因:

            静态成员是单独存储的,并不是对象的组成部分。如果在类的内部进行定义,在建立多个对象时会多次声明和定义该变量的存储位置。在名字空间和作用域相同的情况下会导致重名的问题。

          • 类外初始化的实质是类外定义:

            C++的静态成员实际上需要分配一个内存,不一定需要赋值。初始化是赋一个初始值,而定义是分配内存。静态成员变量在类中仅仅是声明,没有定义,所以要在类的外面定义。 ​在定义或初始化时,全局区为此静态成员变量分配了一块内存。

        • 4. 静态成员变量也有访问权限

      • 访问方法

        • 通过对象:

          Person p1 ; cout<<p1.m_office ;

        • 通过类:

          cout<<Person::m_office ;

    • 静态成员函数

      • 性质

        • 1. 静态成员函数被类中所有的对象共享

        • 2. 只能访问静态成员变量

          非静态属性属于单独的对象,函数没法区别到底是谁的

        • 2. 静态成员函数也有访问权限

  • 对象成员特性:

    • 空类的对象 自动分配1字节空间

      • 原因:

        为了区分空对象占内存的位置 每个对象都有一个独一无二的内存地址,空对象也不例外 这1字节起到“小狗尿尿标记领地”的作用

    • 非静态成员变量 属于类的对象

    • 非静态成员函数 不属于类的对象,只有一份,所有对象共享

      • 那么非静态成员函数如何知道是谁调用自己的呢?——this指针

    • 所有静态成员 不属于类的对象,只有一份,所有对象共享

  • this指针:

    • 性质

      • this指针指向被调用的成员函数所属的对象

        谁调用的这个成员函数,this就指向谁

      • this指针隐含在每一个非静态成员函数中

      • this指针不需要定义,直接使用即可

      • this指针是一个指针常量,指针的指向不可被修改

    • 作用:

      • 1. 解决成员函数形参和成员属性重名的问题

      • 2. 返回对象本身用*this

        • 返回一个匿名对象,该对象属性值与本对象相同:

          Person addage(Person p){ this->m_age += age ; return *this ; }

  • 常函数和常变量

    • 常函数

      • 性质

        • 本质上:在函数后面加const,修饰的是this指针,让指针指向的值(this->)也不能被改变

        • 成员函数后加const后为常函数

        • 常函数内不可以修改成员属性(只读)

        • 成员属性在声明时加关键字mutable才可在常函数中被修改

    • 常对象

      • 性质

        • 声明对象前加const为常对象

        • 常对象中的数据成员为常变量且必须要有初始值

          e,g: Person const p1(22,1)

        • 常对象只能调用常函数

  • 友元 friend

    • 友元的目的是访问另一个类中的私有成员

    • 三种实现

      • 全局函数做友元

        全局函数:在类外声明的函数

        • 将函数声明前加friend放到类的定义的最前边

      • 类做友元

        • 将友元类的声明前加friend放到类的定义的最前边

          • 友元类就可以访问此类的私有属性

      • 成员函数做友元

        • 将成员函数的声明前加friend放到类的定义的最前边,成员函数需要用 类名::来表明是哪一个类里面的成员函数

  • 运算符重载

    • 概念:

      • 对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

    • 分类:

      • 加号运算符重载

        • 作成员函数

          • Person operator+(const Person& p)

        • 作全局函数

          • Person operator+(const Person& p1, const Person& p2)

        • 链式编程思想:

          • 返回值: 类

          • return 临时对象; //临时对象的成员为两对象成员的和

      • 左移运算符重载

        • 作用:自定义输出内容

        • 成员函数 无法实现!

        • 全局函数

          • ostream& operator<<(ostream& cout, Person& p) { out << "a:" << p.m_A << " b:" << p.m_B; return cout;}

        • 链式编程思想:

          • 返回值: ostream &

            • &的解释: ostream对象只能有一个

          • return: cout;

      • 递增运算符重载

        • 以++为例:

          • 前置++:

            先+1

            • 返回值: 类&

            • return *this;

          • 后置++:

            后+1

            • 先用临时对象temp存档: 类 temp=*this;

            • 然后再将*this进行+1

            • 最后返回temp

            • 返回值: 类

              • 注意:不能再加&,因为返回的是temp

                不加&,则返回的是temp的副本,非temp

      • 赋值运算符重载

        • 编译器会自动在类内生成operator=函数,用来进行值拷贝

          c++编译器至少给一个类添加4个函数 1.默认构造函数(无参,函数体为空) 2.默认析构函数(无参,函数体为空) 3.默认拷贝构造函数,对属性进行值拷贝 4.赋值运算符 operator=, 对属性进行值拷贝

        • 如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

        • 重载:

          • 先判断成员堆区有无内存

            • if (m_Age != NULL) { delete m_Age; m_Age = NULL; }

          • 进行深拷贝

            • m_Age = new int(*p.m_Age);

          • return *this;

          • 返回值: 类& //链式编程思想

      • 关系运算符重载

        • 返回值:bool

        • return 0或1

  • 面向对象的三大特性:封装继承多态

  • 文件

    • 类型:

      • 1、文本文件 以ACLL码形式储存在计算机中

      • 2、二进制文件 用户一般不能读懂

    • 操作文件的三大类:

      • 写操作 ofstream

      • 读操作 ifstream

      • 读写操作 fstream

    • 文件打开方式:

      • ios::in 为读文件而打开文件

      • ios::out为写文件而打开文件

      • ios::ate 初始位置为文件尾

      • ios::app 以追加方式写文件

      • ios::turnc 如果文件存在先删除再创建

      • ios::binory 以二进制形式

      • 多种打卡方式用 | 隔开

        e.g. ios::in|ios::out

    • 代码实现:

      • 写文件:

        • 加入头文件<fstream>

          • 创建ofstream对象ofs1

            • 打开文件:ofs1.open("路径+名字.文件类型" , 文件打开方式);

              • 写文件:ofs1 << ... ;

                • 关闭文件:ofs1.close();

所有内容都在个人幕布:

十三、类和对象总览 - 幕布 (mubu.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老油条了!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值