当前位置: 首页 > news >正文

类和对象补充

const 成员函数

const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后面。

void Print() const
 {
 cout << _year << "-" << _month << "-" << _day << endl;
 }

为什么要用const进行修饰

使用const修饰主要就是权限放大缩小的问题,这里我们能看见这里显示报错,那么报错的报错的原因就是权限的放大,这里传入的时候限制是不能改变指向的内容,而接收的权限是可以改变指向的内容,因此涉及权限放大,为了解决这一问题只需要在函数的后面加上const即可把Data *const this ——>const Data *const this。

 const修饰的函数优缺点

通过const进行修改后,普通类型的也可以进行访问被const修饰的函数。这并不意味着所有的都可以这样设置,因为经过修饰后权限被缩小,只能读所指向的内容并不能所指向的内容进行修改。

案例如下:

取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,⼀般这两个函数编译器自动生成的就可以够我们用了,不需要去显示实现。

Date* operator&()

{

        return this; 

}

const Date* operator&()const

{

        return this; 

}

再探构造函数

初始化列表

初始化列表的使用方式式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后面跟⼀个放在括号中的初始值或表达式。注意:每个成员变量在初始化列表中只能出现⼀次

Date(int year = 1, int month = 1, int day = 1)

         :_year(year)

        ,_month(month)

        ,_day(day)

必须使用初始化列表的三种情况

引用成员变量,const成员变量,没有默认构造的类类型成员变量。为什么以上三种要用初始化列表,因为引用必须在定义的时候进行初始化,const也是在初始化的那一刻才能进行初值的改变,没有默认构造,调用的时候需要传参,传参就要初始化,初始化只能在初始化列表中,因为在函数体成员可以出现多次那么到底那个是初始化,这就产出了问题,所以通俗说初始化列表可以认为是每个成员变量定义初始化的地方

面试题分析

初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的的先后顺序无关。建议声明顺序和初始化列表顺序保持⼀致。此题先按照声明的顺序,先执行_a2(),此时a1还未进行传入,这时_a2就会显示随机值,_a1为1。

初始化列表总结

类型转换   

C++⽀持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。如我们学过的指针(虽然存放的是地址,也是有编号)可以和数据类型进行相互转换。

什么是隐式类型转换

A类只有一个单参数的构造函数,因此该构造函数是支持隐式类型转换的,A aa1 = 1;本质上就是隐式类型转换,首先在隐式转换过程中会产生一个临时的中间变量,用1去调用构造函数,得到一个A类型的临时中间变量,然后再用这个A类型的中间变量去调用拷贝构造,最终完成aa1的创建。

#include<iostream>
using namespace std;
class A
{
public:// 构造函数explicit就不再⽀持隐式类型转换 // explicit A(int a1)A(int a1):_a1(a1){}A(int a1, int a2):_a1(a1), _a2(a2){}void Print(){cout << _a1 << " " << _a2 << endl;}
private:int _a1 = 1;int _a2 = 2;
};int main()
{A aa1 = 1;aa1.Print();//用于检测是否创建了中间变量//临时对象具有常性,不能放大权限,如果创建了不加const限定就会报错//const A& aa2 = 1;return 0;
}

explicit的用法

构造函数前加explicit就不再支持隐式类型转换

用法如下:explicit A(int a1)

static关键字

static成员变量的用法

  1. 用static修饰的成员变量,称之为静态成员变量,静态成员变量⼀定要在类外进行初始化。在类外初始化要记得加上类域这要就知道是静态成员变量。
  2. 静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。
  3.  静态成员也是类的成员,受public、protected、private访问限定符的限制。
  4.  静态成员变量不能在声明位置给缺省值初始化,因为缺省值是构造函数初始化列表的,静态成员 变量不属于某个对象,不⾛构造函数初始化列表。

static成员函数的特点

  1. 用static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针。
  2. 静态成员函数中可以访问其他的静态成员,但是不能访问⾮静态的,因为没有this指针。
  3. 非静态的成员函数,可以访问任意的静态成员变量和静态成员函数。
  4. 突破类域就可以访问静态成员,可以通过类名::静态成员或者对象.静态成员来访问静态成员变量 和静态成员函数。

面试小案列

 构造函数的调用顺序是 :先全局然后按照声明的顺序进行构造函数的调用,因此构造函数的调用   顺序为:   C A B D。

析构函数调用的顺序:按照后构造的先析构,最后析构全局的构造函数。所以顺序为:B A D C。

友员补充

友元函数

  1. 在函数声明或者类 声明的前面加friend,并且把友元声明放到⼀个类的里面。
  2.  外部友元函数可访问类的私有和保护成员,友元函数仅仅是⼀种声明,他不是类的成员函数。
  3. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
  4. ⼀个函数可以是多个类的友元函数。

友元类

  1. 友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员。
  2. 友元类的关系是单向的,不具有交换性,如A类是B类的友元,但是B类不是A类的友元。
  3. 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
  4. 有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

 内部类

内部类就是把一个类写在另一个类的里面,这种就叫做内部类。他只是受外部类类域限制和访问限定符限制。内部类并不占用所写入类的字节大小。

注意:内部类默认是外部类的友元类。因此在访问静态成员变量的时候可以直接使用,普通的成员需要引用外部类名。内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用。在内部类上加上private/protected专属内部类,其他地方就无法使用了。

#include<iostream>
using namespace std;
class A
{private:static int _k;int _h = 1;public:class B // B默认就是A的友元 {public:void foo(const A& a){cout << _k << endl; cout << a._h << endl; }private:int b=1;};
};int A::_k = 1;
int main()
{cout << sizeof(A) << endl;A::B b;A aa;b.foo(aa);return 0;
}

 匿名对象

没有名字的对象通常写成类型(实参)。匿名对象生命周期只在当前一行,而有名对象的生命周期是这个main()函数调用结束。匿名对象可以引用,引用后就具有了常性,需要加const加完const之后生命周期变长。

class A

{

        public:

                A(int a = 0)

                        :_a(a)

                {

                        cout <<"A(int a)"<<endl;

                }

                ~A()

                {

                        cout <<"~A()"<<endl;

        private:

                int _a;

};

int main()

{

        //匿名对象的使用方式

        A();

        A(1);

}


http://www.mrgr.cn/news/28373.html

相关文章:

  • [白月黑羽]关于仿写类postman功能软件题目的解答
  • see的本质是什么?
  • Flutter开发之flutter_local_notifications
  • C++11新特性:lambda表达式,包装器,新的类功能
  • 基于机器学习电信号EMG训练分类模型控制仿生手控制系统(Matlab-Simulink实现)
  • Flutter实现绝对定位学习
  • Linux常用命令以及操作技巧
  • 智能体趋势:未来科技的核心驱动力
  • 微信客户量太多难维护?三招提升你的回复效率!
  • 双三次插值及MATLAB实现
  • JavaSE阶段总结
  • C++初阶:STL详解(三)——vector的介绍和使用
  • OpenJudge | 八皇后问题
  • 嵌入式C语言详解与实现
  • 数据库之索引<保姆级文章>
  • floodfill算法(二)
  • robosuite基础教程(一)——基本概念
  • 猫头虎分享:Python库 PyMongo 的简介、安装、用法详解入门教程
  • 【电脑组装】✈️从配置拼装到安装系统组装自己的台式电脑
  • 2024.9最新:CUDA安装,pytorch库安装
  • 代码随想录算法训练营第三十四天 | 62.不同路径,63. 不同路径 II,343.整数拆分,96.不同的二叉搜索树
  • 数据中台建设(六)—— 数据资产管理
  • 图神经网络模型扩展5--3
  • Python数据分析-Steam 收入排名前 1500 的游戏
  • 【Vue3进阶】玩转query传参,让路由管理更轻松
  • Linux3-cp,mv,rm,*