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的一次拷贝。