4.Copy Constructor的构造操作

news2024/9/28 13:27:43

目录

1、对象赋值问题引入

2、Bitwise Copy Semantics(位逐次拷贝)

3、处理class virtual function

4、处理virtual base class subobject


1、对象赋值问题引入

在C++中,有三种情况会以一个object的内容作为另一个class object的初值。这三种情况分别如下:

第一种,显式地以一个object的内容作为另一个class object的初值 X xx = x;

第二种,当object被当作参数交给某个函数时,例如:

extern void foo(X x);
void bar()
{
	X xx;
	//以xx作为foo()的第一个参数初值(隐式的初始化操作)
	foo(xx);
	//...
}

第三种,当一个函数传回一个class object时,例如

X
foo_bar()
{
	X xx;
	//...
	return xx;
}

那么问题来了,以一个object的内容作为另一个class object的初值,C++语言是怎么进行操作的

假设class设计者显示定义了一个copy constructor,像这个样子。

//user-defined copy constructor 的实例
//可以是多参数的形式,其第二参数以及后继参数以一个默认值供应之
X::X(const X &x);
Y::Y(const Y & y,int = 0);

在大部分的情况下,以上的问题将会调用copy constructor。少数情况会执行Bitwise Copy。

如果class没有提供一个explicit copy constructor,当class object以相同的class的另外一个object作为初值,其内部以default memberwise initialization的方法完成。也就是每一个内建的或者派生的data member的值,从一个object拷贝到另外的一个object上。不过它不会拷贝其中的member class object,而是以递归的方式施加memberwise initialization。例如,有一个下面的class声明:

class String
{
public:
	//...没有explicit copy constructor
private:
	char *str;
	int len;
};

对于String verb = noun;语句,他的完成方式像是设定每一个members一样:

//语意相等
verb.str = noun.str;
verb.len = noun.len;

以上是一种memberwise initialization。如果String object是另外一个class的member,像这样子:

class Word
{
public:
	//...没有explicit copy constructor
private:
	int _occurs;
	String _world;
};

对于Word verb = noun;语句,他的完成方式像是设定每一个members一样:

//语意相等
verb.occurs = noun.occurs;//bitwise copy
verb._world = String::String(noun._world);//编译器生成copy constructor,并执行拷贝构造函数

Default constructors和copy constructors在必要的时候才由编译器产生出来。这里“必要的时候”指的是当class不展示bitwise copy semantics时候。

2、Bitwise Copy Semantics(位逐次拷贝)

一个class什么时候不展示“bitwise copy semantics”?有下面的4种情况:

1)当一个class内含一个member object而后者的class声明一个copy constructor时(不论是class设计者显示的声明,还是编译器隐式的合成),例如下面的代码,String显示的声明了,而Word隐式的合成。

class String
{
public:
	String(const char *);
	String(const String &);
	~String();
	//...
};
class Word
{
public:
	Word(const String &);
	~Word();
	//...
private:
	int cnt;
	String str;
};

2)当class继承一个base class而后者存在一个copy constructor时(不论是显示声明还是隐式的被合成)。例如class Dog没有拷贝构造函数,当发生一个Dog object的内容作为另一个Dog object的初值,Dog会被编译器合成一个copy constructor。

class Animal
{
public:
	Animal(const char *);
	Animal(const Animal &);
	~Animal();
	//...
};
class Dog:public Animal
{
public:
	Dog(char * name);
	~Dog();
};

3)当class声明一个或者多个virtual function时。

class Student
{
public:
	Student();
	~Student();
	
	String virtual get_name();
};

4)当class派生自一个继承串链,其中一个或多个virtual base classes时。

class Postgraduate : virtual public Student
{
public:
	Postgraduate();
	~Postgraduate();
	
	String get_Thesis_topic();
};

3、处理class virtual function

在前一节的bitwise copy semantics,提到当class声明一个或者多个virtual function时会被编译器合成一个copy constructor。此外class会进行两种扩张操作:

  • 增加一个virtual function table(vtbl),内含每一个有作用的virtual function的地址。
  • 一个指向virtual function table的指针(vtpr),安插在每一个class object内部。

首先,我定义两个class,ZooAnimal和Bear:

class ZooAnimal
{
public:
	ZooAnimal();
	virtual ~ZooAnimal();
	
	virtual void animate();
	virtual void draw();
	//...
private:
	//ZooAnimal 的animate() 和 draw()
	//所需的数据
};
class Bear : public ZooAnimal
{
public:
	Bear();
	void animate();//译注:虽未写明是virtual,但它其实是virtual
	void draw();//译注:虽未写明是virtual,但它其实是virtual
	virtual void dance();
	//...
private:
	//Bear 的animate() 、 draw() 和 dance()
	//所需的数据	
};

然后,Bear class object以另一个Bear class object作为初值,我可以看到yogi的vptr值拷贝给了winnie的vptr了,这样的操作是安全的,它是通过编译器合成的拷贝构造函数完成的。

最后,当一个base class object以其derived class的object内容做初始化操作时,其vptr复制操作也必须保证安全,例如:

ZooAnimal franny = yogi; //译注:派生类给基类赋值

4、处理virtual base class subobject

Virtual base class 的存在需要特别的处理。一个class object如果以另一个object作为初值,而后者有一个virtual base class subobject,那么也会使“bitwise copy semantics”失效。看看如下继承关系的代码。

class ZooAnimal
{
public:
	ZooAnimal();
	virtual ~ZooAnimal();
	
	virtual void animate();
	virtual void draw();
	//...
private:
	//ZooAnimal 的animate() 和 draw()
	//所需的数据
};

class Raccon : public virtual ZooAnimal
{
public:
	Raccon(){/*设定private data的初值*/}
	Raccon(int val){/*设定private data的初值*/}
	//...
private:
	//所有必要的数据
};

class RedPanda : public virtual Raccon
{
public:
	RedPanda(){/*设定private data的初值*/}
	RedPanda(int val){/*设定private data的初值*/}
	//...
private:
	//所有必要的数据
};

对于如下的代码,little_red和little_critter的关系如下图所示。

RedPanda little_red;
Raccon little_critter = little_red;

在这种情况下,为了完成正确的设定little_critter初值设定,编译器必须合成一个copy constructor,安插一些代码以设定virtual base class pointer/offset的初值。

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

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

相关文章

Upload-labs靶场通过攻略

pass-01 1.写一个一句话木马 2.上传php文件 当我们上传php文件时 提示文件类型不正确 3.修改php后缀 通过修改php后缀为jpg 抓包再次修改成php文件 4.查看是否上传成功 页面显示图片 表示上传成功 pass-02 1.上传一个php文件 页面显示文件类型不正确 2.抓包修改 可以看…

【Python零基础】文件使用和异常处理

文章目录 前言一、从文件中读取数据二、向文件中写入数据三、异常四、存储数据总结 前言 本篇笔者将展示Python如何处理文件数据,包括文件内容的读取和写入操作,以及程序运行时异常模块的处理方式,保证我们写出健壮的代码。 一、从文件中读取…

Nature揭示应变不变的射频电子器件新突破,无线健康监测的前景

【行业背景】 可拉伸电子设备是未来柔性电子技术发展的重要趋势。这些设备在皮肤接口、健康监测、智能穿戴等领域发挥着关键作用,离不开高性能的射频(RF)电子组件。射频电子设备的功能依赖于其基板材料的电气性能,然而传统的弹性…

突发:Runway 从 HuggingFace 上删库跑路,究竟发生了什么?

🔥 突发新闻:Runway 从 HuggingFace 上删库跑路,究竟发生了什么? 1️⃣ Runway 从 HuggingFace 上删库跑路!究竟是技术问题还是另有隐情? 最近科技圈内流传着一则令人瞠目结舌的消息:曾经为AI图…

5款自动生成文案的神器,助你轻松创作优质文案

随着人工智能技术的发展,生活中的很多工作都可以自动化操作,就连创作文案也不再会让人绞尽脑汁的去思考怎么写,因为有了自动生成文案的神器,从而使创作者在写作文案的过程中更加得心应手,并且不费吹灰之力便能拥有优质…

优思学院|精益生产中现场管理的7大工具

在现代制造业中,精益生产(Lean Production)已成为提升生产效率、确保产品质量的关键方法论。精益生产的核心思想在于消除浪费、持续改进,而要实现这些目标,依赖于一系列行之有效的管理工具。在这篇文章中,我…

爆品是测出来的,不是选出来的

我在亚马逊摸爬滚打了五年,深深感受到了"七分选品,三分运营"的重要性。不管你的产品图片、描述多么精美,如果不去精选和测试,很难保证能出单。我见过很多跨境新手在选品上卡了几个月,纠结于卖什么。但实际上…

一次VUE3 使用axios调用萤石云OpenAPI踩坑经历

通过调用萤石云的获取设备列表功能,我们可以根据 ACCESS_TOKEN 获取该用户下的设备列表。 Python 调用接口 根据接口文档[1],使用Python,很轻松就能获取到该列表,代码如下(该代码用于拼接生成vue代码,这是…

爱浦路云化核心网:支持百万用户规模,构筑超快海量连接网络

广州爱浦路网络技术有限公司(简称:IPLOOK)是全球领先的4G/5G/6G核心网厂商,致力于向全球客户提供端到端的移动通信解决方案,其产品和服务覆盖了卫星通信、能源通信、电网通信等多个重要领域。经过十二年的探索与发展&a…

英文论文格式编辑(二)

这里写自定义目录标题 正文部分段落格式段落对齐方式conclusion图片左右对齐 正文部分段落格式 出现下面这种箭头,是使用了标题格式 在这个样式里面修改 包括图片啥的,都别用标题格式,按道理来说,一个标题的箭头是能把下面的内…

如何构建短视频矩阵?云微客开启多账号协同作战

你有没有疑惑过,为什么有些账号每一次发布视频,都要艾特一下其他账号呢?那些被艾特的账号,你有点进去关注过吗?其实做过运营的都或多或少的接触过矩阵,短视频矩阵的玩法现在也逐步成为了趋势。企业通过多账…

深度学习分类模型训练代码模板

深度学习分类模型训练代码模板 简介 参数模块 采用argparse模块进行配置,便于服务器上训练,以及超参数记录。在服务器上进行训练时,通常采用命令行启动,或时采用sh脚本批量训练,这时候就需要从命令行传入一些参数&a…

弱电工程交换机选型有哪些误区

在弱电工程中,交换机的选型是一个至关重要的环节,然而,很多工程师和项目负责人常常在这一环节中犯下一些误区,影响了整个系统的性能和稳定性。首先,许多人对于交换机的理解停留在价格的考量上,追求低价而忽…

什么是VOCs和NOx排放物?

朗观视觉小编观察发现,VOCs(Volatile Organic Compounds)和NOx(Nitrogen Oxides)是两种常见的空气污染物,它们对环境和人类健康都有重要影响。 VOCs(挥发性有机化合物) VOCs是指在常…

docker文档

一、docker概述 1、java项目通过docker打包成镜像(包含了所有的环境)放到docker仓库中,只需要下载发布的镜像直接运行即可; 2、虚拟机技术的缺点: 资源占用多、冗余步骤多、启动很慢 容器化技术: 比较do…

Linux系统-文件属性

语法格式 设置chattr /- perm filename 查看lsattr filename [rootlocalhost jian]# man chattr 用于改变文件属性,常用到的就是a i 只能在追加模式写入内容 不能被修改、删除、重命名,不能创建链接文件,大部分源数据也不能被修改 文…

PD协议沟通过程

引言 Power Delivery(PD)协议是一种由USB-IF(USB Implementers Forum)定义的电力传输与管理标准,旨在通过单一线缆同时为设备提供高速数据传输和灵活的电力传输能力。PD协议支持从5V到20V甚至更高电压的电力传输&…

Spring Boot实现发QQ邮件

​ 博客主页: 南来_北往 系列专栏:Spring Boot实战 引言 尽管电子邮件已不再是主流的沟通方式,但在职场中仍有不少人偏好使用邮件进行交流。这不仅仅是为了通信,更重要的是作为一种正式的工作记录,确保客户对自己曾经提出的…

客服系统简易版

整体架构解读 客服端和商城端都通过websocket连接到客服系统, 并定期维持心跳当客户接入客服系统时, 先根据策略选择在线客服, 然后再发送消息给客服 websocket实现 用netty实现websocket协议, 增加心跳处理的handler, 详见chat-server模块 客服路由规则 暂时仅支持轮询的…

WIN 系统中英文翻译神器"STranslate"再也不怕看不懂了

随着机器翻译工具的不断发展,翻译工作者的工作效率和效果得到了大幅提升。这些工具不仅可以提供快速的翻译参考,还可以帮助处理大量的文本,极大地节省了翻译的时间和精力。翻译也可以花更多的时间去精修译文,在机翻的“半成品”之…