C++之构造函数拷贝
拷贝构造函数,顾名思义,就是通过拷贝对象的方式创建一个新对象。拷贝构造函数有两种原型(我们继续以book类来说明拷贝构造函数原型):
book(book &b);
book(const book &b); //下面一种原型则规定在创建新对象的时候不得修改被拷贝的对象
这两种原型都是book类对象的引用。下面一种原型则规定在创建新对象的时候不得修改被拷贝的对象。如果拷贝构造函数的参数不是对象的引用,则是不允许的。如下面这种构造函数形式则是无法编译通过的。
book(book b); //无法编译过去
为什么拷贝构造函数的参数一定要是对象的引用呢?我们可以想一下,如果不是引用,而是通过传值的方式将实参传递给形参,这中间本身就要经历一次对象的拷贝的过程,而对象拷贝则必须调用拷贝构造函数,如此一来则会形成一个死循环,无解。所以拷贝构造函数的参数必须是对象的引用。
拷贝构造函数除了能有对象引用这样的参数之外,同样也能有其它参数。但是其它参数必须给出默认值。例如下面这种拷贝构造函数声明方式。
book(const book &b, price = 5.0);
如果类的设计人员不在类中显示的声明一个拷贝构造函数,则系统会自动地为类生成一个拷贝构造函数,自动生成的拷贝构造函数功能简单,只能将源对象的所有成员变量一一复制给当前创建的对象。
class book
{
public:
book(){}
book(book &b);
book(char* a, double p = 5.0);
void display();
private:
double price;
char * title;
};
book::book(book &b)
{
price = b.price;
title = b.title;
}
book::book(char* a, double p)
{
title = a;
price = p;
}
void book::display()
{
cout<<"The price of "<<title<<" is $"<<price<<endl;
} int main()
{ char A[] = {,,,,};
book math{A,};
book yuwen(math);
//book::price =8; //次行不能编译成功 因为price变量是私有的成员 类外不能访问
yuwen.display();
math.display();
return ;
}
在本例中的book类中就声明了一个拷贝构造函数book(book &b);当然这个拷贝构造函数跟系统默认生成的拷贝构造函数功能是一样的,也就只是实现了数据成员的对应拷贝功能。
了解了拷贝构造函数的声明及定义方式,我们再来看一下我们在设计类的时候,什么时候才需要设计拷贝构造函数,我们先来看下面一个例子,相信看完之后会有一定领会,之后再来揭晓答案。
#include<iostream>
using namespace std; class Array
{
public:
Array(){length = ; num = NULL;};
Array(int * A, int n);
void setnum(int value, int index);
int * getaddress();
int getlength(){return length;}
void display();
private:
int length;
int * num;
}; Array::Array(int *A, int n)
{
num = new int[n];
length = n;
for(int i=; i<n; i++)
num[i] = A[i];
} void Array::setnum(int value, int index)
{
if(index < length)
num[index] = value;
else
cout<<"index out of range!"<<endl;
} void Array::display()
{
for(int i=; i<length; i++)
cout<<num[i]<<" ";
cout<<endl;
} int * Array::getaddress()
{
return num;
} int main()
{
int A[] = {,,,,};
Array arr1(A, );
arr1.display();
Array arr2(arr1);
arr2.display();
arr2.setnum(,);
arr2.display();
arr1.display();
cout<<arr1.getaddress()<<" "<<arr2.getaddress()<<endl;
return ;
}
程序运行结果如下:
1 2 3 4 5
1 2 3 4 5
1 2 8 4 5
1 2 8 4 5
00331F58 00331F58
在本例中,我们重新定义了一个Array类,可以理解为一个整形数组类,这个类中我们定义了两个成员变量:整形指针num和数组长度length。
类中定义了一个默认构造函数,声明了一个带参构造函数。默认构造函数很简单,带参构造函数则是用于将一个已有的数组全部拷贝给类对象。
除了两个构造函数之外,我们还定义四个成员函数,一个是用于修改数组中数值的setnum函数、一个打印数组中所有元素的display函数、一个返回数组首地址的函数getaddress和一个返回数组长度的函数getlength。除了默认构造函数之外和getlength函数之外,所有的函数在类外都有定义。
#include<iostream>
using namespace std;
class Array
{
public:
Array(){length = ; num = NULL;};
Array(int * A, int n);
Array(Array &a);
void setnum(int value, int index);
int * getaddress();
void display();
int getlength(){return length;}
private:
int length;
int * num;
};
Array::Array(Array & a)
{
if(a.num != NULL)
{
length = a.length;
num = new int[length];
for(int i=; i<length; i++)
num[i] = a.num[i];
}
else
{
length = ;
num = ;
}
}
Array::Array(int *A, int n)
{
num = new int[n];
length = n;
for(int i=; i<n; i++)
num[i] = A[i];
}
void Array::setnum(int value, int index)
{
if(index < length)
num[index] = value;
else
cout<<"index out of range!"<<endl;
}
void Array::display()
{
for(int i=; i<length; i++)
cout<<num[i]<<" ";
cout<<endl;
}
int * Array::getaddress()
{
return num;
}
int main()
{
int A[] = {,,,,};
Array arr1(A, );
arr1.display();
Array arr2(arr1);
arr2.display();
arr2.setnum(,);
arr2.display();
arr1.display();
cout<<arr1.getaddress()<<" "<<arr2.getaddress()<<endl;
return ;
}
看看这个两个有什么不同。对象的地址变了。
C++之构造函数拷贝的更多相关文章
- C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数
构造函数 ,是一种特殊的方法 .主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 .特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数 ...
- 【c++ primer, 5e】构造函数 & 拷贝、赋值和析构
[构造函数] 1.构造器就是创建对象时被调用的代码. 2.如果没有自定义构造器,那么编译器将自动合成一个默认的无参构造器. 3.自定义的构造器不允许加const,所创建const的对象只有在构造器代码 ...
- 拷贝构造函数 & 拷贝赋值运算符
一.拷贝构造函数 1. 形式 class A { public: // ... A(const A &); // 拷贝构造函数 }; 2. 合成拷贝构造函数 编译器总会为我们合成一个拷贝构造函 ...
- [c++基础]3/5原则--拷贝构造函数+拷贝赋值操作符
/* * main.cpp * * Created on: Apr 7, 2016 * Author: lizhen */ #include <iostream> #include &qu ...
- C++的转换构造函数、拷贝构造函数、赋值运算符重载
1 转换构造函数 C++的转换构造函数是只有一个参数的构造函数.当程序试图将一个其他类型的对象或基本类型值赋给该类的一个待初始化对象时(如Person p="Dean";) ...
- 如何避免被C++默认拷贝构造函数忽悠?
一.背景介绍 因为工作关系,需要用到C++编程.对于我来说,虽然一直从事的是linux平台下的嵌入式软件开发,但深入用到C++的特性的地方并不多.对于C++,用得最多的无非是指针. ...
- C++ 拷贝构造函数、拷贝赋值运算符、析构函数
每一次都会忘,做个笔记吧.想到哪里写到哪里. 拷贝构造函数 第一个参数必须是自身类类型的引用,且任何额外参数都有默认值.(为什么必须是引用?见后解释) 合成拷贝构造函数:如果我们没有为一个类定义拷贝构 ...
- C++对象模型的那些事儿之四:拷贝构造函数
前言 对于一个没有实例化的空类,编译器不会给它默认生成任何函数,当实例化一个空类后,编译器会根据需要生成相应的函数.这类函数包括一下几个: 构造函数 拷贝构造函数 析构函数 赋值运算符 在上一篇博文C ...
- C++中构造函数,拷贝构造函数和赋值函数的区别和实现
C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法.下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象 ...
随机推荐
- Entity FrameWork(实体框架)是以ADO.NET Entity FrameWork ,简称为EF
Entity FrameWork(实体框架)是以ADO.NET Entity FrameWork ,简称为EF Entity FrameWork的特点 1.支持多种数据库(MSSQL.Oracle.M ...
- CentOS 7 镜像下载
新版本系统镜像下载(当前最新是CentOS 7.4版本) CentOS官网 官网地址 http://isoredirect.centos.org/centos/7.4.1708/isos/x86_64 ...
- ubuntu 18.04 设置固定ip
# This file is generated from information provided by # the datasource. Changes to it will not pers ...
- Date类型错误
今天写代码的时候遇到一个很蛋疼的问题,明明实体类写的是Date型,文本框也是date型,数据库中对应的列是dateTime类型,这原本进行数据录入或者是修改这个操作是不应该出错的,但是一时没找到解决的 ...
- 从零开始学习html(十五)css样式设置小技巧——下
六.垂直居中-父元素高度确定的单行文本 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8&quo ...
- web界面 之 登录 (初稿)
web登录一般注意以下几点: 1)拥有元素:用户名,密码(密码字符显示与隐藏功能),登录按钮,忘记密码链接(忘记用户名链接),注册链接 2)用户体验: •页面显示,光标默认停在第一个输入框 利用htm ...
- 自定义适用于手机和平板电脑的 Dynamics 365(三):显示的实体
您可以启用 适用于手机的 Dynamics 365 和 适用于平板电脑的 Dynamics 365 的有限实体集. 若要查看是否启用了实体,或者要启用实体,请单击“设置”>“自定义”>“自 ...
- Atitit.播放系统规划新版本 and 最近版本回顾 v3 pbf.doc 1 版本11 (ing)41.1 规划h5本地缓存系列 41.2 Android版本app41.3 双类别系统,
Atitit.播放系统规划新版本 and 最近版本回顾 v3 pbf.doc 1 版本11 (ing)4 1.1 规划h5本地缓存系列 4 1.2 Android版本app4 1.3 双类别系统, ...
- [Android] 针对生成的图片文件在系统Gallery不显示的处理
之前遇到过一个问题,就是发现我在程序中生成一个新的 Bitmap 之后,当我打开系统的 Gallery 查看时,并没有看到新生成的图像.然而打开文件浏览器,找到保存 Bitmap 所在的文件夹下,还能 ...
- gradle中的compileSdkVersion和buildToolsVersion
CompileSdkVersion:编译版本,就是运行这个项目需要的SDK,即API Level. buildToolsVerson:是构建工具的版本,构建工具包括了打包工具aapt.dx等等. 注意 ...