C++关于类(下)

本文详细解释了C++中的运算符重载、赋值运算符(包括const成员和自定义类型)、构造函数的初始化列表、explicit关键字、静态成员、友元功能以及内部类等概念,探讨了编译器在处理这些内容时的优化策略。
摘要由CSDN通过智能技术生成

   6 赋值运算符重载

6.1运算符重载

        C++为了增强代码可读性引入了运算符重载,运算符重载是具有特殊函数名的函数。跟普通函数一样具有返回值,函数名字,形参列表。

函数名字为:关键词(operator)接上一个运算符。如:operator+。

函数原型:返回值+operator+运算符+形参列表。

运算符重载有几点注意事项:

  1. 不能通过连接其他符号来创建新的操作符。
  2. 重载操作符必须有一个类类型参数
  3. 作为类成员函数重载时,有一个形参是隐藏的(*this),传递的时候比当全局函数少一个形参。
  4. .*, sizeof, ?: , .(点) ,:: 这五个操作符是不能进行重载的。
  5. 用于内置类型的操作符不能改变它的含义。

一个日期类函数对于-= 与- 的实现:

6.2 赋值运算符

  1. 赋值运算符重载格式:

1.1:参数类型:const 类&,传递引用可以提高效率,传进来的值是不可以改变的

1.2: 返回值类型:类&,返回引用可以提高效率,可以进行连续赋值。

        返回*this。

        检查是否有自我赋值这种浪费时间的操作。

    2. 赋值运算符只能重载类的成员函数不能重载全局函数。

        原因:因为赋值运算符作为六大天选之子中的一个,没有对它进行显示实现的,编译器在类中会默认生成一个赋值运算符。此时,在类外进行全局函数的赋值运算符重载会与类内的形成冲突,所以赋值运算符只能作为类内成员函数。

        3. 没有显示定义,默认生成的赋值运算符对于内置类型会进行字节序的值拷贝。对于自定义类型会调用对应的赋值运算符重载。

        4. 编译器默认生成的赋值运算符可以应对日期类的自定义类型,但对于资源申请的自定义类是需要自己写赋值运算符的。如若不写是进行了值拷贝,会占用一个空间。所以对需要涉及资源管理的需要自己写赋值运算符。

6.3 前置++与后置++重载

        前置++与后置++都是一元运算符,为了能让前置++与后置++能正确的形成重载。

        C++中规定了前置++的写法为: 返回类型+operator++()

        后置++:返回类型+operator++(int)  比前置++多了一个int

 

7 Const成员

7.1 概念

        将const放在函数名后面,用const修饰的成员函数称为const成员函数。const是用来修饰成员函数的隐形形参*this的。被cnst修饰的成员函数对该类的实列(*this)所有的成员变量都不能被改变。注意:const放在函数名后面只能用来修饰成员函数。

        编译器对const成员对象的处理:

7.2问题

请思考下面的几个问题:

  1. const对象可以调用非const成员函数吗?
  2. 非const对象可以调用const成员函数吗?
  3. const成员函数内可以调用其它的非const成员函数吗?
  4. 非const成员函数内可以调用其它的const成员函数吗?

1.const对象可以调用非const成员函数吗?

        不可以。因为const对象是一个只读对象,非const对象是一个可读可写的对象,调用非const对象,就是将const对象传给非const对象,是一个权限放大。

2. 非const对象可以调用const成员函数吗?

        可以的 因为const对象是一个只读对象,而非const是一个可读可写的对象,将非const对象传给const是一种权限的缩小。

3. const成员函数内可以调用其它的非const成员函数吗?

        不可以。const修饰的*this,如果一个成员函数被声明为 const,那么在这个成员函数中,对于该类的实例(即*this)的所有成员变量都是不可修改的。而非const成员函数是可以修改的所以不行。

4 .非const成员函数内可以调用其它的const成员函数吗?

        可以的。因为非const是可以修改的,调用const成员函数只是一种权限的缩小。

7.3总结

  1. 对于函数成员内部需要修改的就不用加上const修饰了。而需要修改的就需要加上const防止被需改
  2. 被加上const的成员函数,普通的对象和const对象都是可以修改的。

8.取地址及const取地址重载        

        取地址及const取地址也是默认成员函数,也是6大天选之子的最后两个默认成员函数。我们不编写编译器也会进行默认生成。这两个符号我们不需要重新生成,编译器生成的已经足够使用了,只有特殊情况下才需要,比如不想让别人获得类的地址如:

9 再谈构造函数

9.1构造函数体赋值

        在创建对象的时候,编译器通过调用函数,给对象中的成员变量赋值。

        该构造函数在调用的时候会给成员变量一个初始值。但是这种行为不能称为初始化,只能称为在构造函数中进行一次赋值。因为初始值只有一次,而构造函数体内可以进行多次赋值。我们需要在一个位置给成员变量进行初始化。

9.2初始化列表

        初始化列表:以一个冒号开始,以逗号进行分割,给成员变量进行一次初始化。

        这个初始化列表是为了给只能初始化一次的成员变量而做出来的。比如const修饰的成员变量,引用,自定义类型成员。它还可以完成对自定义类型成员默认构造函数的初始化。

几点注意事项:

  1. 每个成员变量初始化只能出现一次
  2. 初始化的顺序是和声明顺序一样的,和初始化顺序无关

        3. 自定义类成员(没有默认构造函数时),const成员变量,引用成员变量必须放在初始化列表初始化

        4. 无论有没有放在初始化列表,编译器都会在初始化列表进行成员变量初始化。自定义类型会调用它的构造函数。

10 explicit关键词

   单个参数

        该关键词是用来禁止类型转化的。

        构造函数不仅可以构造与初始化对象。还可以对单个参数或者除第一个参数其他参数均均有默认值的有强制类型转化作用。

加了关键字explicit就不能强制类型转化会报错

多个参数

        多个参数类似于数组使用{}进行初始化的。

11 Static成员

11.1概念

        声明为static的类成员称为类的静态成员。用static修饰的成员函数称为静态成员函数。用static修饰的成员变量称为静态成员变量。静态成员变量一定要在类外进行初始化。

11.2特性

  1. 静态成员变量是一个类所有对象共享的,不属于某个具体的对象,存放在静态区。
  2. 静态成员函数的优点在于:即使不存在类的对象,它们也存在,并且可以调用。

  1. 静态成员变量不能调用非静态成员变量
  2. 静态成员变量不能被const修饰。因为没有*this指针
  3. 静态成员函数不能调用非静态成员函数。
  4. 非静态成员函数可以调用静态成员函数与静态变量
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

12友元

12.1友元函数

        友元是一种突破封装的方式,它可以让类外的函数访问类内的私有数据。虽然友元可以增加耦合度,但是会破坏封装,所以不宜多用。

        现在想要实现类通过<<打印到屏幕上,需要进行operato<<的重载。但是在类内定义重载会导致类的实例化在左边,cout在右边。所以需要进行全局函数的重载。这是要将cout重载在左边。但类外的数据访问不到类内的私有数据,这就需要友元来解决。

        友元函数可以直接访问私有类成员,它是定义在类外的普通函数,不属于任何的类,需要在类中声明加关键词friend。

Operator<<在类中重载是会缺少一个形参,*this的。

说明:

  1. 友元函数不能被const对象修饰,因为它不是成员对象
  2. 友元函数不是成员函数,不属于类内
  3. 友元函数可以访问类中的所有成员
  4. 友元函数可以在类中任何地方声明,不受类访问限定符的限制
  5. 一个函数可以是多个类的友元函数
  6. 友元函数与普通函数调用方法相同

12.2友元类

友元类可以访问另外一个类中的所有成员。友元类的成员函数都是另一个类的友元函数。

  1. 友元类是单向,不是双向的,不具备交换性质

如:Time是Date类的友元类,不能说明Date是Time的友元类。

  1. 友元类不能传递。

不能说A是B的友元,B是c的友元,就说A是C的友元。

  1. 友元关系不能继承。

13 内部类

  1. 一个类定义在另一个类的内部,这个类就叫另一个类的内部类。内部类是一个独立的类,它不属于外部类,无法通过外部类实例化的对象去访问内部类。外部类对内部类没有优越的访问权限。
  2. 内部类是外部类的友元函数。可以通过外部类的对象参数来访问外部类的所有成员。但外部类不是内部类的友元函数。
  3. 内部类可以定义在外部类的public,pravate,protected的任何一个地方
  4. 内部类可以直接访问外部类的静态成员变量,不需要外部类的对象/类名。
  5. Sizeof(外部类)=没有定义内部类的外部类,不计算内部类的大小。

14 匿名对象

15 拷贝对象时的编译器优化

在传值和返回传参时,编译器会做一些优化,这些优化还是很有效果的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值