C++的转换构造函数、拷贝构造函数、赋值运算符重载
1 转换构造函数
C++的转换构造函数是只有一个参数的构造函数。当程序试图将一个其他类型的对象或基本类型值赋给该类的一个待初始化对象时(如Person p=”Dean”;),就会尝试调用转换构造函数。
转换构造函数可以通过设置默认值的方法同无参构造函数在同一函数体内进行定义。定义语句形式如下:
1: <类型名> ( <参数类型> 参数名 = <参数默认值> )
2: {
3: //函数实现
4: }
2 拷贝构造函数
拷贝构造函数是用一个对象来初始化另一个对象的构造函数。构造函数的参数是该类对象的一个常引用。拷贝构造函数会在以下三种情况下被调用:
(1)用类的一个对象去初始化另一个对象。
(2)函数的形参是类对象,调用函数时形参和实参结合会调用拷贝构造函数。
(3)函数的返回值是一个类对象,返回时会用拷贝构造函数构造一个临时对象。
拷贝构造函数的定义形式为:
1: <类型名>( const <类型名>& <参数名> )
2: {
3: //函数实现
4: }
3 赋值运算符重载
赋值运算符的重载是为了实现将一个对象赋给另一个对象。如果编程人员不实现赋值运算符的重载,系统会自动生成一个版本。
赋值运算符重载需要一个参数,该参数是对另一个类对象的常引用,返回值是对象本身的引用。其定义形式如下:
1: <类型名>& operator = ( const <类型名>& <参数名> )
2: {
3: //函数实现
4: }
4 程序实例
先定义一个Person类:
1: #include <iostream>
2: #include <string>
3: int No=1;
4: class Person
5: {
6: public:
7: Person(std::string name="Unknown")
8: {
9: if(name=="Unknown")
10: std::cout<<"无参构造函数被调用! ";
11: else
12: std::cout<<"类型转换构造函数被调用! ";
13: this->name=name;
14: this->no=No++;
15: std::cout<<name<<" "<<no<<std::endl;
16: }
17: Person(const Person &P)
18: {
19: std::cout<<"拷贝构造函数被调用! ";
20: this->no=P.no+10;
21: this->name=P.name;
22: std::cout<<name<<" "<<no<<std::endl;
23: }
24: Person& operator =(const Person p)
25: {
26: std::cout<<"重载运算符=被重载! ";
27: this->name=p.name;
28: this->no=p.no;
29: std::cout<<name<<" "<<no<<std::endl;
30: return *this;
31: }
32: ~Person()
33: {
34: std::cout<<"析构函数被调用! ";
35: std::cout<<this->name<<" "<<this->no<<std::endl;
36: }
37: void Output()
38: {
39: std::cout<<"此处调用Output方法输出:";
40: std::cout<<name<<" "<<no<<std::endl;
41: }
42: private:
43: int no;
44: std::string name;
45: };
下面是具体的调用方法:
1: #include "Person.h"
2: Person Output(Person p)
3: {
4: p.Output();
5: std::cout<<"-------------------------------------------"<<std::endl;
6: return p;
7: }
8: int main()
9: {
10: Person p1;
11: std::cout<<"==========================================="<<std::endl;
12: Person p2="Dean";
13: std::cout<<"==========================================="<<std::endl;
14: p1=Output(p2);
15: std::cout<<"==========================================="<<std::endl;
16: Person p3(p2);
17: system("pause");
18: return 0;
19: }
运行的结果如下:

程序的执行顺序如下:
(1)调用了无参构造函数,默认给p1对象的name赋值为Unknown,no赋值为1。
(2)用字符串常量“Dean”来初始化对象p2,此处调用了转换构造函数。
(3)调用Output函数。该过程比较复杂,其中的详细执行过程包括:
a)形参和实参结合,系统会复制p2作为参数。此时会调用Person类的拷贝构造函数,通过输出可以看到该临时对象是p2的一个副本。
b)调用p2副本的Output方法输出。
c)返回阶段。由于返回值是一个Person类的对象,所以会生成一个临时对象作为返回值,而返回值是通过拷贝构造函数复制了参数的各成员。由函数定义可以看到,main函数调用的Output函数实际上返回的是参数的一个副本,也就是穿进去的实参p2的副本的副本,临时对象在调用拷贝构造函数时输出的no为22也说明了这一点。
(4)将Output函数的返回值赋给p1。p1获取了p2副本的副本的各成员后该临时对象就析构了。
(5)用p2来初始化p3。这是拷贝构造函数的最普通的应用,通过输出可以看到p3是p2的一次拷贝。
C++的转换构造函数、拷贝构造函数、赋值运算符重载的更多相关文章
- C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数
构造函数 ,是一种特殊的方法 .主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中 .特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数 ...
- C/C++(C++拷贝构造器,赋值运算符重载)
拷贝构造器 由己存在的对象,创建新对象.也就是说新对象,不由构造器来构造,而是由拷贝构造器来完成.拷贝构造器的格式是固定的. class 类名 { 类名(const 类名 & another) ...
- C++中构造函数,拷贝构造函数和赋值函数的区别和实现
C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法.下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象 ...
- C++中的构造函数,拷贝构造函数,赋值函数
C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法.下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象 ...
- 如何避免被C++默认拷贝构造函数忽悠?
一.背景介绍 因为工作关系,需要用到C++编程.对于我来说,虽然一直从事的是linux平台下的嵌入式软件开发,但深入用到C++的特性的地方并不多.对于C++,用得最多的无非是指针. ...
- C++对象模型的那些事儿之四:拷贝构造函数
前言 对于一个没有实例化的空类,编译器不会给它默认生成任何函数,当实例化一个空类后,编译器会根据需要生成相应的函数.这类函数包括一下几个: 构造函数 拷贝构造函数 析构函数 赋值运算符 在上一篇博文C ...
- C++构造函数和拷贝构造函数详解
构造函数.析构函数与赋值函数是每个类最基本的函数.它们太普通以致让人容易麻痹大意,其实这些貌似简单的函数就象没有顶盖的下水道那样危险. 每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包含 ...
- C++ 类 & 对象-类成员函数-类访问修饰符-C++ 友元函数-构造函数 & 析构函数-C++ 拷贝构造函数
C++ 类成员函数 成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义. 需要强调一点,在 :: 运算符之前必须使用类名.调用成员函数是在对象上使用点运算符(.),这样它就能操作与 ...
- C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量
// 同类之间无私处 2构造函数 3析构函数 4构造函数的种类和析构函数的顺序 结论:析构函数的调用顺序,跟对象的构造顺序相反,谁先构造,谁最后一个被析构. 拷贝构造函数: 注意: 等号写在下面和写在 ...
随机推荐
- 有关ftp批量传送文件或文件夹
以ftp 批量上传文件时 可以用 mput file1 file2 .. 但是这样没传送一个就会问是否传送下一个 ,那么可以使用prompt这个命令.这是个双向开关,执行一次是取消提示,在执行一次是打 ...
- [转]各种字符串Hash函数比较
转自:https://www.byvoid.com/zht/blog/string-hash-compare 常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些 ...
- ubuntu下PHP支持cURL
公司项目需要,注册需要验证手机号码,其中需要LAMP支持cURL.由于事先安装平台的时候,并没有注意到这一点,所以编译PHP5的时候,并没有使用参数--with-curl.后来需要的时候,查一些参考方 ...
- STL学习系列一:STL(标准模板库)理论基础
STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间. STL的从广 ...
- 如何创建一个有System用户权限的命令行
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:如何创建一个有System用户权限的命令行.
- JavaScript要点(八) 闭包
JavaScript 变量可以是局部变量或全局变量. 私有变量可以用到闭包. 全局变量 函数可以访问由函数内部定义的变量,如: function myFunction() { var a = 4; r ...
- Java的位运算符实例——与(&)、非(~)、或(|)、异或(^)
一.Java的位运算符实例——与(&).非(~).或(|).异或(^) 1.与(&) 0 & 2 = 0 0 0 0 0 1 0 0 1 0 2.非(~) ~0 = 7 0 0 ...
- cocos2d-x 手势之简单实现
转自:http://blog.sina.com.cn/s/blog_61ece099010187tl.html 手势之前也发过一篇,但是我感觉那个还不够轻巧. 而且大多数游戏里面不会有那么复杂的手势, ...
- linux就是这个范儿之融于心而表于行(1)
原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 .作者信息和本声明.否则将追究法律责 时间总是过得那么快,如流水一般哗啦啦的就淌走了一大堆!周遭事事沧桑变迁喧哗或耳语中流传的故事已渐模糊 ...
- MyEclipse 10官网下载地址以及破解方法
刚刚公布了MyEclipse 10,我如今用的还是6.5的版本号,6.5的版本号是我认为最好用的一个版本号. 我装上了,还没感受到有哪些好用,就是感觉体积庞大,和IBM 的WID一样,是个多面手,啥事 ...