类和对象-4

news2024/9/20 4:58:47

文章目录

  • 前言
  • const成员函数
  • 取地址及const取地址操作符重载
  • 构造函数续
    • explicit
  • static成员
  • 友元
  • 内部类
  • 匿名对象

前言

在前面的文章中,我们了解到了类的四个默认成员函数:构造、析构、拷贝构造和赋值重载。接下来我们会继续学习剩下的两个默认成员函数以及类和对象的一些细节语法。
那么在了解剩下的两个成员函数前,我们先来学习一下const成员函数

const成员函数

首先有如下场景:

class A
{
public:
	void Print()
	{
		cout << "Success" << endl;
	}
private:
	
};
int main()
{
	const A a;
	a.Print();
	return 0;
}

在这里插入图片描述

如上我们只是想调用A的print函数,这个函数不会改变任何值,但实际上我们运行不了这个代码。
这又是我们的隐藏this指针的锅了,每个成员函数的参数里面都有一个隐藏的this指针参数,更关键的是这个this指针没有被const修饰哦!
这又是一个典型的权限放大了,我们的a是被const修饰的,但是this指针却没有被const修饰,因此解决方法就是让this指针也被const修饰,具体方法也很简单:“)”后加const即可。

class A
{
public:
	void Print()const
	{
		cout << "Success" << endl;
	}
private:
	
};
int main()
{
	const A a1;
	a1.Print();
	A a2;
	a2.Print();
	return 0;
}

在这里插入图片描述
由此可知,当成员函数被const修饰时,既可以传入const修饰的类也可以传入没有被const修饰的类。
因此,在成员函数不需要修改类的属性时,最好用const修饰成员函数。

取地址及const取地址操作符重载

那么了解了const成员函数后,我们就可以揭开最后两天默认成员函数的庐山真面目了。
那就是取地址操作符重载const取地址操作符重载
没错,由于const成员函数的存在,这个简单的操作符重载竟然分成了两份。其实仔细想想上一个默认成员函数是赋值重载,这个刚好要改变类的属性,因此不能被const修饰。不然六个默认成员函数可能就变成了七个默认成员函数了。
那么这两个默认成员函数存在的意义又是什么呢?
这当然是为了构成逻辑自洽了:由于我们对自定义类型用的操作符往往都是要重载的,而取地址这个操作符不可以说不重要,简直就是c++的灵魂所在,因此编译器会默认生成取地址的重载。因而,我们绝大多场景用编译器默认生成的取地址重载就已经足够了,除非,你想实现一些特殊的功能。比如悄悄传个空地址回去:

class A
{
public:
	A* operator&()
	{
		return (A*)nullptr;
	}
private:	
};

咳咳,除了这些特殊的场景外。我们是不需要手码这两个默认成员函数的。

构造函数续

在前面我们已经学到了构造函数的一些基础用法,但由于知识的局限性,构造函数的一些其他特点还没有详谈。仔细想想构造函数的定义是不是要我们初始化一个类来着,最终我们的类的属性也的确获得了一些初始值,但那真的是初始化么?
就像这样:

class B
{
public:
	B(int x)
	{
		_x = x;
		_x++;
		_x = 1;
	}
private:
	int _x;
};

这里我们对_x进行了多次赋值,最终我们的确得到了_x的值为1,但这完全谈不上是初始化吧。
如果这个案例还不够深刻请看下面的例子:

class B
{
public:
	B(int x,int& ry)
	{
		_x = x;
		_x++;
		_x = 1;
		_ry = ry;
	}
private:
	int _x;
	int& _ry;
};

如上,我们尝试对_ry这个成员变量进行初始化,但貌似这个写法就是前面提及的引用初始化的经典错误写法啊。
关于引用这种变量是要被初始化的,既然上述方式不可行,那真正可行的方式是怎样的呢?
不多卖关子了,如下所示:

class B
{
public:
	B(int x, int& ry)
		:_x(x)
		, _ry(ry)
	{
	}
private:
	int _x;
	int& _ry;
};

当我们需要初始化时要写这样一个初始化列表,以“:”开始,以“,”分隔,成员变量(初始化值)。下面的函数体想写什么都可以。
这种略显丑陋的函数,就是我们构造函数真正的初始化方式啦!
它有以下特点:

  • 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  • 类中包含以下成员,必须放在初始化列表位置进行初始化:
    引用成员变量
    const成员变量
    自定义类型成员(且该类没有默认构造函数时)
  • 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
    也就说:
class C
{
public:
	C(int x)
		:_x(x)
		,_y(_x)
	{
	}
	void Print()
	{
		cout << _x << ' ' << _y << endl;
	}
private:
	int _y;
	int _x;
};
int main()
{
	C c(10);
	c.Print();
	return 0;
}

在这里插入图片描述
正确的做法应该是将x赋给_y,_y赋给_x.

	C(int x)
		:_x(_y)
		,_y(x)
	{
	}

在这里插入图片描述

explicit

谈及构造函数就不得不提一个有意思的东西:隐式类型转换
对于构造函数为单参数的类支持隐式类型转换,

class D
{
public:
	D(int x)
	:_x(x)
	{
	}
private:
	int _x;
};
D d=1;

上述代码实则是将1转换成了D然后再拷贝构造给d,但有些编译器会对其优化,使得d能够直接以1为参数构造,因此这里就不多做验证了。
那么对于多参的构造函数能否也转换呢?
C++11以后就规定了多参构造函数也可以隐式类型转换了:

class E
{
public:
	E(int x,int y)
	:_x(x)
	,_y(y)
	{
	}
private:
	int _x;
	int _y;
};
E e={1,1};

当然如果你不想发生这种类型转换,认为代码是严谨的,就可以用explicit来修饰构造函数,禁止类型转换:

class E
{
public:
	explicit E(int x,int y)
	:_x(x)
	,_y(y)
	{
	}
private:
	int _x;
	int _y;
};

static成员

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

使用场景有实现一个类,计算程序中创建出了多少个类对象。

class A
{
 public:
	 A() { ++_scount; }
	 A(const A& t) { ++_scount; }
	 ~A() { --_scount; }
	 static int GetACount() { return _scount; }
 private:
	 static int _scount;
 };
 int A::_scount = 0;
 
 void TestA()
 {
	 cout << A::GetACount() << endl;//静态成员函数可以用作用域限定符调用
	 A a1, a2;
	 A a3(a1);
	 cout << A::GetACount() << endl;
 }

特点:

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

友元

在前面日期类的实现,我们已经浅谈过友元了。友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
友元函数:在类的任何一处用friend 函数声明,就可以使得这个函数在类外也可以调用类的保护、私有对象。

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数
  • 友元函数不能用const修饰(因为const修饰的是this指针,而友元函数不是类的成员函数所以没有this指针)
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数的调用原理相同

友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
跟友元函数定义相差无几,有以下特点:

  • 友元关系是单向的,不具有交换性。
  • 友元关系不能传递
  • 友元关系不能继承

啊! 这种关系让我想起了我的高等代数课,真是有种代数学的美啊。O.o
关于友元呢,大家对他的评价褒贬不一、两极分化。有人认为它破坏了类的封装是罪大恶极的,也有人觉得友元提供了一种不用写Get函数的便利。事实上任何事物都可以是一把双刃剑,就看你怎么使用罢了。就拿C++来说,有人拿他开发游戏、编写系统,也有人会用来开发非法软件、牟取暴利。所以,只要合适地使用友元,不刻意、恶意地破坏封装,我觉得问题是不大的。

内部类

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

内部类就是外部类的友元类,但是外部类不是内部类的友元。
老实说,这多少有点抽象了。是不是像极了含辛苦茹养育孩子长大的父母,父母的东西属于孩子,但是孩子的东习…
emmmm。不得不提的是内部类的使用场景非常罕见,所以没必要过多纠结。

匿名对象

这里来的我目前所掌握的类和对象的最后一个知识点了。
正如c语言可以申请匿名结构体一样,我们的类也可以申请匿名对象。要注意好区别哦,是结构体匿名,但这里不是类匿名而是对象匿名哦!

class F
{
public:
	F(int x=0)
	:_x(x)
	{
	}
	void Print()
	{
		cout<<Hehe<<endl;
	}
private:
	int _x;
};
int main()
{
	F();
	F(1);
	F().Print;
	return 0;
}

如上我们演示了匿名类的构造方式以及使用场景。

  • 注意到,匿名对象可以F()形式构造,但有名对象不可以F f(),因为编译器会识别成函数声明
  • 匿名对象的声明周期只有对应的那一行哦!

那么类和对象的内容就到此结束了,希望对读者有所帮助呢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1535690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CAD建筑版2024 安装教程

CAD建筑版是一种专门用于建筑设计和绘图的CAD软件版本。它提供了专业的建筑设计工具和功能&#xff0c;帮助建筑师、设计师和工程师在建筑领域进行快速、准确和高效的设计工作。 CAD建筑版具备建筑相关的库和元素&#xff0c;用户可以方便地使用预定义的建筑符号和元素进行建筑…

二叉树|104.二叉树的最大深度 111.二叉树的最小深度

104.二叉树的最大深度 力扣题目链接 class solution { public:int getdepth(TreeNode* node) {if (node NULL) return 0;int leftdepth getdepth(node->left); // 左int rightdepth getdepth(node->right); // 右int depth 1 max(leftdepth, rightdepth…

嵌入式-4种经典继电器驱动电路-单片机IO端口/三极管/达林顿管/嵌套连接

文章目录 一&#xff1a;继电器原理二&#xff1a;单片机驱动电路三&#xff1a;经典继电器驱动电路方案3.1 继电器驱动电路方案一&#xff1a;I/O端口灌电流方式的直接连接3.1.1 方案一的继电器特性要求3.1.2 方案一可能会损坏I/O口 3.2 继电器驱动电路方案二&#xff1a;三极…

记录一次基于AES加密的恶意软件逆向分析和解密过程(含文件)

导入(Imports)和字符串 首先,用IDA或Ghidra加载文件test.dat,文件为64位文件 IDA点击View==>Open subviews==>Imports,查看导入信息 Ghidra可以直接看到 可以看到,导入函数有: __printf_chk, malloc, __isoc99_sscanf, putchar, __stack_chk_fail, __cxa_fina…

安捷伦Agilent E8361C网络分析仪

181/2461/8938产品概述&#xff1a; 安捷伦e 8361 c网络分析仪提供通用网络分析&#xff0c;可选软件和/或硬件为您的应用定制-如多端口、脉冲射频等。 安捷伦E8361C网络分析仪的显示窗口数量不限&#xff0c;可以调整大小和重新排列&#xff0c;每个窗口最多有24条活动轨迹和…

CSS 脱离标准文档流 浮动

浮动 在标准流当中&#xff0c;元素或者标签在页面上摆放的时候会出现不如意的地方。要想解决这些问题可以采用脱离标准流的方式来进行解决这些问题&#xff0c;脱离标准流也称为脱离文档流。 脱离标准流的解决方式有三种&#xff0c;一种是浮动&#xff0c;另外一种是固定定位…

【Flask】Flask项目结构初识

1.前提准备 Python版本 # python 3.8.0 # 查看Python版本 python --version 安装第三方 Flask pip install flask # 如果安装失败&#xff0c;可以使用 -i&#xff0c;指定使用国内镜像源 # 清华镜像源&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple/ 检查 Flask 是…

大数据分析-基于Python的电影票房信息数据的爬取及分析

概要 现如今&#xff0c;人民群众对物质生活水平的要求已不再局限于衣食住行&#xff0c;对于精神文化有了更多的需求。电影在我国越来越受欢迎&#xff0c;电影业的发展越来越迅猛&#xff0c;为了充分利用互联网技术的发展&#xff0c;掌握电影业的态势&#xff0c;对信息进行…

【3GPP】【核心网】【4G】4G手机接入过程,手机附着过程(超详细)

1. 4G手机接入过程&#xff0c;手机附着过程 附着&#xff08;Attach&#xff09;&#xff1a; 终端在PLMN中注册&#xff0c;从而建立自己的档案&#xff0c;即终端上下文 进行附着的三种情况&#xff1a; ①终端开机后的附着&#xff0c;初始附着 ②终端从覆盖盲区返回到…

全栈的自我修养 ———— uniapp中加密方法

直接按部就班一步一步来 一、首先创建一个js文件填入AES二、创建加密解密方法三、测试 一、首先创建一个js文件填入AES 直接复制以下内容 /* CryptoJS v3.1.2 code.google.com/p/crypto-js (c) 2009-2013 by Jeff Mott. All rights reserved. code.google.com/p/crypto-js/wi…

(ROOT)KAFKA详解

生产篇 使用 /** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE file distributed with* this work for additional information regarding copyright ownership.* The ASF licenses this file to Y…

使用Windows的“远程桌面连接”Ubuntu主机连接不上问题解决

问题描述&#xff1a; 使用Windows自带的“远程桌面连接”来连接自己的Ubuntu的系统的过程中&#xff0c;自己已经成功安装了 xrdp 文件包&#xff0c;但是在使用“远程桌面连接”时&#xff0c;自己的“远程桌面连接”软件在输入Ubuntu系统的用户名和密码后&#xff0c;连接不…

LRU的设计与实现-算法通关村

LRU的设计与实现-算法通关村 缓存是应用软件的必备功能之一&#xff0c;在操作系统&#xff0c;Java里的Spring、mybatis、redis、mysql等软件中都有自己的内部缓存模块&#xff0c;而缓存是如何实现的呢&#xff1f;在操作系统教科书里我们知道常用的有FIFO、LRU和LFU三种基本…

Java-SSM房租租赁系统

Java-SSM房租租赁系统 1.服务承诺&#xff1a; 包安装运行&#xff0c;如有需要欢迎联系&#xff08;VX:yuanchengruanjian&#xff09;。 2.项目所用框架: 前端:JSP、jquery、bootstrap等。 后端:SSM,即Spring、SpringMvc、Mybatis等。 3.项目功能点: 3-1.后端房东功能: 1.…

linux学习之Socket

目录 编写socket-udp 第一步&#xff0c;编写套接字 第二步&#xff0c;绑定端口号 第三步&#xff0c;启动服务器&#xff0c;读取数据 第四步&#xff0c;接收消息并发回信息给对方 编写socket-Tcp 第一步&#xff0c;编写套接字 第二步&#xff0c;绑定端口号 第三步…

解读BGInfo配置命令

命令行中的第一条命令是用于修改Windows注册表的&#xff0c;具体解释如下&#xff1a; reg add HKEY_CURRENT_USER\Software\Sysinternals\BGInfo /v EulaAccepted /t REG_DWORD /d 1 /f reg add&#xff1a;这是一个用来向Windows注册表添加或修改键值的命令行指令。HKEY_C…

『scrapy爬虫』10. 实战爬取自己的csdn信息(详细注释步骤)

目录 1. 数据库建表2. 搭建项目环境创建项目新建爬虫虚拟环境中安装库 定义数据类型(item.py)爬虫(spiders/csdn.py)管道(pipelines.py)中间件(middlewares.py)项目设置(setting.py)运行测试总结 欢迎关注 『scrapy爬虫』 专栏&#xff0c;持续更新中 欢迎关注 『scrapy爬虫』 …

Git进阶用法:Git分支轻松使用,配有图文

一、文章内容 git和分支相关的概念.git和分支有关的命令.git项目实战环节. 二、相关概念 分支&#xff1a;分支的概念好比树干的分支&#xff0c;每一跟分支都是从主干分出来的&#xff0c;营养是主干给的&#xff0c;所以在git里主干和分支也是如此&#xff0c;在git里主分…

HBCalculator 程序:通过 VMD 可计算分子动力学模拟中氢键密度和强度的一维和二维分布

分享一个通过 VMD 可计算分子动力学模拟中氢键密度和强度的一维和二维分布程序 HBCalculator。 感谢论文的原作者&#xff01; 主要内容 “氢键是分子系统中关键的非共价相互作用&#xff0c;对生物、化学和能量相关过程产生重大影响&#xff1b;因此&#xff0c;描述氢键信息…

Leetcode 70.爬楼梯

心路历程&#xff1a; 这道题是之前学院的一道复试题&#xff0c;大家都没怎么刷过算法题&#xff0c;只记得当年凭借几次试错自己把这道题做出来了&#xff0c;当时也不知道动态规划之类的。 正常来讲&#xff0c;这种找不到循环结构的题一般都是递归解决。 注意的点&#x…