1:当函数以相应的类作为形参列表时,对象可以作为函数的参数传入。在学习函数时,我们曾提过,值传递先复制实参产生副本。那么对象的副本是怎样的呢?

复制构造函数是指类的对象被复制时所调用的函数。下面两种情况中对象都会调用复制构造函数。

(1)将一个对象赋值给另外一个对象时。例如:

对象1=对象2;

对象1(对象2);

上面的程序中对象2的复制构造函数会被调用。

(2)作为值传递的实参。例如:

function(对象1);

在function函数体内,使用的是对象1的副本。所以之前会调用对象1的复制构造函数。

和构造函数一样,C++在未发现自定义的复制构造函数之前会创建一个默认的构造函数。

自定义的复制构造函数的声明格式为:

类名(类名& 形参)

值得注意的是,复制构造函数时引用传递的函数。既然默认复制构造函数已经完成复制工作,那为何需要重新定义它呢?例如,一个类具有指针类型的数据,默认复制构造函数执行之后,原对象和副本的指针成员指向的是同一个内存空间。通过指针改变该内存,就会改变两个对象实际应用的数据(也就是这块内存的内容)。这时可以自定义复制构造函数,将两个指针的内存分离开。

2:代码如下:

(1)germ.h

#include <string>
using std::string;
class germ{
public:
int m_age;
string m_name;
germ(germ& g);//自定义复制构造函数 类名(类名&形参)
germ(string s);//构造函数
~germ();//析构函数,执行收尾工作
};

(2)germ.cpp

#include "stdafx.h"
#include "germ.h"
#include <iostream>
using std::cout;
using std::endl;
germ::germ(string s)
{
m_name = s;
m_age = ;
cout<<"发现了"<<m_name<<endl;
}
germ::germ(germ& g)
{
g.m_age +=;
this->m_age = ;
this->m_name =g.m_name + "的复制体";
cout<<"产生了"<<g.m_name<<"的复制体"<<endl;
}
germ::~germ(){
cout<<this->m_name<<"被消灭了"<<endl;
}

(3)main.cpp

// 7.7.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream>
#include "germ.h"
using std::cout;
using std::endl;
germ copyGerm(germ gc)
{
return gc;
}
int main()
{
germ g1("有氧菌");//(发现了有氧菌)
germ g2(g1);//第一个germ的意思是声明一个对象g2,g2(g1)的意思是将g1赋值给g2,此时将会调用复制构造函数(产生了有氧菌的复制体)
germ g3("无氧菌");//(发现了无氧菌)
germ g4 = g3;//意思同样是将g3赋值给g4,此时将会调用复制构造函数。(产生了无氧菌的复制体)
germ g5 = copyGerm(g4);//此时也调用复制构造函数了,只要有副本,就会调用复制构造函数。此处调用了两次,copygerm()一次,等号一次(产生了无氧菌复制体的复制体,产生了无氧菌复制体的复制体的复制体)
return ;
}
//注意,调用copygerm后,copygerm会立即被释放,所以会立即放出析构函数,输出(无氧菌的复制体的复制体被消灭了)
//以后依次g5,g4,g3,g2,g1被释放,故依次被输出这些被消灭

运行结果:

从程序运行结果来分析代码:首先在主函数中产生了g1对象,由复制构造函数产生了g1的复制体g2——有氧菌复制体。之后定义了g3——无氧菌。通过复制构造函数产生了g3的复制体g4。前四行输出即是上面所述的过程。g5的产生前,g5所在赋值语句等号右边的copyGerm函数被调用,传递的实参为g4——无氧菌的复制体。如同开始提到的,值传递实参对象产生副本,副本就是形参gc——无氧菌复制品的复制品。函数执行完毕后,传递回临时变量,内容是gc。g5的值经过复制语句,所以它是gc(临时变量使用的内存)的复制品。

C++入门经典-例7.7-对象与复制,菌类的繁殖的更多相关文章

  1. C++入门经典-例7.8-const对象,标准尺寸

    1:当建立一个对象之后,如果不希望它的任何数据发生改变,可以将其直接声明为const对象,例如: const 类名 对象名 const对象必须初始化.我们可以调用它的数据和函数,但是不可以对他们进行修 ...

  2. C++入门经典-例6.6-字符串复制

    1:字符串复制函数strcpy的格式如下: strcpy(字符数组名,字符串) 其作用是把字符串中的字符串复制到字符数组中.需要注意的是,字符串结束标志'\0'也一同被复制. 注意是将后面的内容复制给 ...

  3. 《挑战30天C++入门极限》C++类对象的复制-拷贝构造函数

        C++类对象的复制-拷贝构造函数 在学习这一章内容前我们已经学习过了类的构造函数和析构函数的相关知识,对于普通类型的对象来说,他们之间的复制是很简单的,例如: int a = 10; int ...

  4. C++入门经典-例7.6-this指针,同一个类的不同对象数据

    1:对于类的非静态成员,每个对象都有自己的一份拷贝,即每个对象都有自己的数据成员,不过成员函数却是每个对象共享的.那么调用共享的成员函数如何找到自己的数据成员呢?答案是通过类中隐藏的this指针. 2 ...

  5. C++入门经典-例7.10-运算符的重载,重载加号运算符

    1:曾经介绍过string类型的数据,它是C++标准模版库提供的一个类.string类支持使用加号“+”连接两个string对象.但是使用两个string对象相减确实非法的,其中的原理就是C++所提供 ...

  6. C++入门经典-例9.3-类模板,简单类模板

    1:使用template关键字不但可以定义函数模板,而且可以定义类模板.类模板代表一族类,它是用来描述通用数据类型或处理方法的机制,它使类中的一些数据成员和成员函数的参数或返回值可以取任意数据类型.类 ...

  7. C++入门经典-例8.10-实现抽象类中的成员函数

    1:抽象类通常作为其他类的父类,如果从抽象类派生的子类是抽象类,则子类必须实现父类中的所有纯虚函数.代码如下: // 8.10.cpp : 定义控制台应用程序的入口点. // #include &qu ...

  8. C++入门经典-例8.9-抽象类,纯虚函数,创建纯虚函数

    1:包含有纯虚函数的类称为抽象类,一个抽象类至少具有一个纯虚函数.抽象类只能作为基类派生出的新的子类,而不能在程序中被实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针.在程序开发过程中并 ...

  9. C++入门经典-例8.8-虚继承

    1:以前讲到从CBird类和CFish类派生子类CWaterBird时,在CWaterBird类中将存在两个CAnimal类的复制.那么如何在派生CWaterBird类时使其只存在一个CAnimal基 ...

随机推荐

  1. shell 中的 set -e 和 set +e的区别

    区别: set -e : 执行的时候如果出现了返回值为非零,整个脚本 就会立即退出 set +e: 执行的时候如果出现了返回值为非零将会继续执行下面的脚本 set -e 命令用法总结如下:1. 当命令 ...

  2. LeetCode 腾讯精选50题--有效的括号

    根据题意,第一反应就是使用栈,左右括号相匹配,则将左括号出栈,否则将左括号入栈. 这里我用数组配合“指针”模拟栈的入栈与出栈操作,初始时指针位置指向0,表示空栈,凡遇上左括号则直接入栈,若遇上有括号, ...

  3. docker之常见错误

    1. docker run -d --name showdoc -p 4999:80 -v /showdoc_data/html:/var/www/html/ star7th/showdoc WARN ...

  4. ubuntu下安装vue/cli提示No command 'vue' found

    通过官方指令 npm install -g @vue/cli 安装vue脚手架提示: No command 'vue' found, did you mean: Command 'vpe' from ...

  5. 编译安装带lua 的 vim 编辑器

    注:支持7.4以后的vim版本 安装lua dev库yum -bcurrent install lua-devel 编译vim带lua支持,安装到/home/sy120714/software/vim ...

  6. vscode 头部注释插件

    1.安装 在vs商店搜索koroFileHeader 2.进入vscode的设置里边搜索fileheader.customMade 3.修改配置信息 "fileheader.customMa ...

  7. webpack升级4出现的问题

    webpack3升级到4出现了很多问题,经过验证报错信息如下 1 Module parse failed: Unexpected token (:) You may need an appropria ...

  8. win10编译maskrcnn benchmark

    步骤 1. 按照官网的Option1安装步骤安装 https://github.com/facebookresearch/maskrcnn-benchmark/blob/master/INSTALL. ...

  9. 初次安装虚拟机WindowsServer2016

    因学习需要,安装windosServer2016,遇到了几个小坑,特地分享一下. 一.windows server 2016 登录 在登录是会出现 输入CTRL+ALT+DEL,才能响应进入用户界面, ...

  10. xenserver 下载模板

    cd /tmp rm -rf Auto.sh wget http://os.xensystem.net/XenSystem/download/Customer/Auto.sh sh Auto.sh