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.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象 ...
随机推荐
- EF Codefirst(二)数据注释
CodeFirst通过分析我们在代码里编写的类,以及类之间的关系生成数据库表,以及表之间的各种关系.数据库的表会涉及到主键,外键,列是否为空,列类型等等. 我们要通过怎样的方式来暴露这些信息呢? ...
- ThinkPHP实现登陆功能
思路:前台输入账号密码,后台自定义一个函数checkNamePwd()用于验证账号密码正确与否,在控制器里调用,其中,checkNamePwd()方法验证账号密码正确性是首先通过账号查找密码,然后把查 ...
- python 约束,异常处理与MD5加密
1. 类的约束 1. 写一个父类. 父类中的某个方法要抛出一个异常 NotImplementedError (重点) 2. 抽象类和抽象方法 # 语法 # from abc import ABCMet ...
- SQLServer 学习笔记之超详细基础SQL语句 Part 1
Sqlserver 学习笔记 by:授客 QQ:1033553122 1创建数据库 格式: CREATE DATABASE database_name ON PRIMARY(在组文件组中指定文件) ( ...
- 开源免费的文档协作系统 onlyoffice平台轻松部署
请移步至此,更详细:http://blog.csdn.net/hotqin888/article/details/79337881 ONLYOFFICE是一个免费的.开源的企业办公套件,用于在线组织团 ...
- java EE 监听器
生命周期监听器与属性改变监听器都必须使用@WebListener或在web.xml中声明,容器才会知道要加载.读取相关的监听器.
- Oracle EBS FA 资产编号跳号
- YYYY-mm-dd HH:MM:SS大小写解释
d 月中的某一天.一位数的日期没有前导零. dd 月中的某一天.一位数的日期有一个前导零. ddd 周中某天的缩写名 ...
- 运维安全之Tripwire
转自网络 Tripwire是最为著名的unix下文件系统完整性检查的软件工具,这一软件采用的技术核心就是对每个要监控的文件产生一个数字签名,保留下来. 当文件现在的数字签名与保留的数字签名不一致时,那 ...
- 转:SQL中 patindex函数的用法
语法格式:PATINDEX ( '%pattern%' , expression ) 返回pattern字符串在表达式expression里第一次出现的位置,起始值从1开始算. pattern字符串在 ...