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

探索C++对象模型:流插入提取探讨、const修饰、初始化列表(下篇)

 

前引:在C++语言长达三十余年的演进历程中,每一次标准更新都在试图平衡性能与抽象、控制与安全之间的微妙关系。从C++11引入的"现代C++"范式开始,开发者得以在保留底层控制能力的同时,借助语言特性大幅提升代码的可维护性与安全性。本文聚焦于类与对象,初始化列表与构造函数究竟有何关系!const又是如何解决隐藏的被修改问题的~

目录

自动识别—探讨

流插入识别自定义类型

流提取识别自定义类型

总结

连续流插入

连续流提取

const成员

问题

解决方法

初始化列表

引入

初始化列表

必须使用初始化列表的情景

(1)const成员初始化

(2)引用成员

(3)无默认构造函数的类型成员

初始化顺序

效率比较


自动识别—探讨

难道编译器可以自动识别内置类型真的是“自动”吗?

这是因为C中需要一律先指明类型,再去打印出来;而C++中是在库里面帮我把准备工作都做完了,我们就可以直接使用了,例如:

 因此我们可以判断,如果需要编译器自动识别自定义类型,那么需要函数重载完成

我们可以看到流插入、流提取的类型是:

流插入识别自定义类型

下面我们通过成员函数重载的方式来实现流插入,但是我们看到如果流插入作参数是无法通过编译

St2 << cout;
void operator<<(ostream& out);
void Timedate::operator<<(ostream& out)
{out << _year << "年" << _month << "月" << _day << "日" << endl;
}

双操作数的运算符规定:

第一个参数是左操作数,第二个参数是右操作数。而运算符重载函数的第一个形参被 this 指针隐式占用了,ostream类对象的引用在第二个形参位置,所以在调用运算符重载时,只能是this指针指向的对象在运算符的左边,cout对象在运算符的右边,但这又不符合留提取的含义

这样我们跟库里面的实现是不同的,也感觉到不适。解决方法是在成员函数外面实现,使用友元

void operator<<(ostream& out, Timedate& St2)
{out << St2._year << "年" << St2._month << "月" << St2._day << "日" << endl;
}

友元:对外面定义的函数声明前面加上“friend”即可,这样可以解决无法访问私有成员的问题,友               元设置的位置只要在类里面就可以,无论是私有还是公共

下面我们看实际效果:

流提取识别自定义类型

有了上面的经验,我们这里使用友元快速实现流提取

函数声明:

void operator>>(istream& in, Timedate& St2);

函数实现:

void operator>>(istream& in, Timedate& St2)
{in >> St2._year >> St2._month >> St2._day;
}

 效果展示:

总结

 我们用成员函数去实现流插入、提取自定义类型是不符合使用习惯的,因为 this 指针占用了第一个参数位置;因此需要考虑参数位置问题,这就得在类外实现,同时友元解决访问类私有成员问题

连续流插入

可以看到我们自定义识别是无法连续的,这是因为函数实现时我们指定了类型是 void

对于一般的赋值顺序是:从右往左

对于流提取、插入顺序是:从左往右(如:cout<<St2 然后 cout<<St1)

因此我们需要改变函数的返回值问题!

 函数声明:

friend ostream& operator<<(ostream& out, Timedate& St2);

函数实现:

ostream& operator<<(ostream& out, Timedate& St2)
{out << St2._year << "年" << St2._month << "月" << St2._day << "日" << endl;return out;
}

 效果展示:

连续流提取

原理和上面的一样,提取顺序也是从左往右,我们直接实现!

函数声明:

istream& operator>>(istream& in, Timedate& St2);

函数实现:

istream& operator>>(istream& in, Timedate& St2)
{in >> St2._year >> St2._month >> St2._day;return in;
}

const成员

问题

将const修饰的“成员函数”称之为const成员函数

const修饰类成员函数,实际修饰该成员函数 隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。这样一定安全了吗?

例如:

下面这种虽然不能对St2进行修改,但是是可以对 *this 指向进行修改的

bool operator==(const Timedate St2);

解决方法

对于不需要更改的隐含参数(*this),我们可以在函数声明和定义后面加上 const 

例如:

初始化列表

引入

在实例化对象时,不管是编译器还是我们自己,会使用构造函数给成员变量一个合适的初始值。

但是经过构造函数之后,我们还不能将其称为成员变量的初始化:

构造函数中的语句只能称为赋初值,而不能称作初始化

因为初始化只能初始化一次,而构造函数体内可以多次赋值

初始化列表

什么是初始化列表:

初始化列表是构造函数的一部分,用于在对象创建时直接初始化成员变量

初始化列表与构造函数关系:

构造函数初始化有两种方式:函数体赋值、初始化列表

所以二者结合才是完整的初始化哦!

如何写初始化列表:

(1)以一个冒号开始,接着是一个以逗号分隔的数据成员列表

(2)每个 "成员变量" 后面跟一个放在括号中的初始值或表达式

class Mytime
{
public:Mytime(int year, int month, int day):_year(year),_month(month),_day(day){//构造函数体功能部分}private:int _year;int _month;int _day;
};
必须使用初始化列表的情景
(1)const成员初始化

const 成员变量必须在声明时初始化,且之后不能修改

class Mytime
{
public:Mytime(int year, int month, int day):_year(year),_month(month),_day(day){//构造函数体功能部分}
private:const int _year;int _month;int _day;
};

否则就会报错:

(2)引用成员

引用必须在声明时绑定到某个对象

class Mytime
{
public:Mytime(int year, int month, int day):_year(year),_month(month),_day(day){//构造函数体功能部分}
private://const成员const int _year;//引用int& _month;int _day;
};

但是我们给初始化时传来的参数用引用类型 ,原因如下: 

(1)引用是变量的别名,加上引用就直接是外部的值给成员里面的引用进行赋值

(引用可以赋值引用)

原因:引用的赋值实际是对原对象的赋值,并不修改原来的绑定关系 (多个引用可指向同一象)

(2)如果不用引用,那么初始化函数结束,变量也就销毁了,引用无对象了

正确写法应该是:

(3)无默认构造函数的类型成员

首先我们知道尽管自己不写构造函数,编译器也会调用自己的构造函数,但是它区分内置、自定义

在初始化时:默认构造不会对自定义类型进行处理

class Mytime
{
public:Mytime(int year, int month):_year(year), _month(month), newnode(((Mytime*)malloc(sizeof(Mytime) * 5))){//构造函数体功能部分//对空间进行判断if (newnode == nullptr){perror("空间失败\n");return;}}
private://const成员const int _year;//引用int& _month;//自定义成员Mytime* newnode;
};

初始化顺序

初始化列表中成员的初始化顺序与类中成员声明的顺序是一致的,而非初始化列表顺序

例如:

效率比较

对于自定义类型:

初始化列表:直接调用成员的构造函数 

构造函数体内赋值:先调用默认构造函数,再进行赋值

对于内置类型:

无明显差异

                                                   【雾非雾】期待与你的下次相遇!  

相关文章:

  • 图像去雾算法研究报告
  • 记录python在excel中添加一列新的列
  • 【场景分析】基于概率距离快速削减法的风光场景生成与削减方法
  • 构建安全AI风险识别大模型:CoT、训练集与Agent vs. Fine-Tuning对比
  • Maven:在原了解基础上对pom.xml文件进行详细解读
  • 【MySQL系列】 MySQL 中的 TINYINT 类型
  • 如何用事件风暴构建领域模型?
  • 梯度优化提示词:精准引导AI分类
  • 【Redis】分布式缓存的一系列问题(持久化,主从集群,哨兵,分片集群)
  • CMake基础:CMakeLists.txt 文件结构和语法
  • 深入理解 Redis 哨兵模式
  • 理论篇五:如何优化Webpack的打包速度
  • React从基础入门到高级实战:React 基础入门 - React Hooks 入门
  • [创业之路-374]:企业战略管理案例分析-战略制定/设计-市场洞察“五看”:看宏观之当前的国际环境、国家产业政策中的机会与风险
  • C++搜索二叉树
  • [docker]更新容器中镜像版本
  • 项目中使用到了多个UI组件库,也使用了Tailwindcss,如何确保新开发的组件样式隔离?
  • 创新项目实训开发日志7
  • Java基础 Day19
  • spring中的InstantiationAwareBeanPostProcessor接口详解
  • 网站租用服务器多少钱/网站推广排名收费
  • 可以用手机做网站吗/百度推广工资多少钱一个月
  • 湖南网站建设的公司排名/关键词seo排名优化推荐
  • 网站建设资料/枣庄网站seo
  • 机关网站建设存在的问题/站长之家whois查询
  • 上海专业做网站公司/百度网站首页提交入口