在进行深拷贝的时候,我既重载了赋值栈的赋值 运算符重载有自定义了一个拷贝构造函数.

南开大学2015春学期《面向对象程序设计》在线作业_答案_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
南开大学2015春学期《面向对象程序设计》在线作业_答案
||暂无简介
高级计算机讲师|
总评分3.7|
浏览量3110
阅读已结束,如果下载本文需要使用5下载券
想免费下载本文?
下载文档到电脑,查找使用更方便
还剩4页未读,继续阅读
你可能喜欢为什么在类里要重载operator=和拷贝构造函数
[问题点数:40分,结帖人congcongying]
为什么在类里要重载operator=和拷贝构造函数
[问题点数:40分,结帖人congcongying]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2007年9月 C/C++大版内专家分月排行榜第三2007年8月 C/C++大版内专家分月排行榜第三2006年11月 C/C++大版内专家分月排行榜第三
2014年10月 C/C++大版内专家分月排行榜第三2014年4月 C/C++大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。posts - 109,&
comments - 56,&
trackbacks - 0
关键词:构造函数,浅拷贝,深拷贝,堆栈(stack),堆heap,赋值运算符
&&&&在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。
&&&&如果对象在申明的同时马上进行的初始化操作,则称之为拷贝运算。例如:
&&&&&&&&class1 A("af"); class1&B=A;
&&&&&此时其实际调用的是B(A)这样的浅拷贝操作。
&&&&如果对象在申明之后,在进行的赋值运算,我们称之为赋值运算。例如:
&&&&&&&&class1 A("af"); class1 B;
&&&&&&&&B=A;
&&&&&&&&此时实际调用的类的缺省赋值函数B.operator=(A);
&&&&&&&&不管是浅拷贝还是赋值运算,其都有缺省的定义。也就是说,即使我们不overload这两种operation,仍然可以运行。
那么,我们到底需不需要overload这两种operation 呢?
&&&&&&&&答案就是:一般,我们我们需要手动编写析构函数的类,都需要overload 拷贝函数和赋值运算符。
&下面介绍类的赋值运算符
1.C++中对象的内存分配方式
&&&&&&&&在C++中,对象的实例在编译的时候,就需要为其分配内存大小,因此,系统都是在stack上为其分配内存的。这一点和C#完全不同!千 万记住:在C#中,所有类都是reference type,要创建类的实体,必须通过new在heap上为其分配空间,同时返回在stack上指向其地址的reference.
&&&&&&&&因此,在C++中,只要申明该实例,在程序编译后,就要为其分配相应的内存空间,至于实体内的各个域的值,就由其构造函数决定了。
&&&&例如:
&&&&A(int&id,char&*t_name)
&&&&name=new&char[strlen(t_name)+1];
&&&&strcpy(name,t_name);
&&&&private:
&&&&&&&&char *
&&&&&&&&int _
int&main()
A&a(1,"herengang");
在程序编译之后,a和b在stack上都被分配相应的内存大小。只不过对象a的域都被初始化,而b则都为随机值。
其内存分配如下:
2. 缺省情况下的赋值运算符
&&&&如果我们执行以下:
&&&&&&&&则其执行的是缺省定义的缺省的赋值运算。所谓缺省的赋值运算,是指对象中的所有位于stack中的域,进行相应的复制。但是,如果对象有位于heap上的域的话,其不会为拷贝对象分配heap上的空间,而只是指向相同的heap上的同一个地址。
&&&&&&&&执行b=a这样的缺省的赋值运算后,其内存分配如下:
&&&&&&&&因此,对于缺省的赋值运算,如果对象域内没有heap上的空间,其不会产生任何问题。但是,如果对象域内需要申请heap上的空间,那么在析构对象的时候,就会连续两次释放heap上的同一块内存区域,从而导致异常。
&&&&{&&&&&&&&
&&&&&&&&delete&
3.解决办法--重载(overload)赋值运算符
&&&&&&&&因此,对于对象的域在heap上分配内存的情况,我们必须重载赋值运算符。当对象间进行拷贝的时候,我们必须让不同对象的成员域指向其不同的heap地址--如果成员域属于heap的话。&&&&
因此,重载赋值运算符后的代码如下:
&&&&A(int&id,char&*t_name)
&&&&&&&&_id=
&&&&&&&&name=new&char[strlen(t_name)+1];
&&&&&&&&strcpy(name,t_name);
&&&&A&&operator&=(A&&a)
//注意:此处一定要返回对象的引用,否则返回后其值立即消失!
&&&&&&&&&&&&if(name!=NULL)
&&&&&&&&&&&&&&&&
&&&&&&&&this-&_id=a._
&&&&&&&&int&len=strlen(a.name);
&&&&&&&&name=new&char[len+1];
&&&&&&&&strcpy(name,a.name);
&&&&&&&&return&*this;
&&&&&&&&cout&&"~destructor"&&
&&&&&&&&delete&
&&&&char&*
int main()
&A a(1,"herengang");
其内存分配如下:
这样,在对象a,b退出相应的作用域,其调用相应的析构函数,然后释放分别属于不同heap空间的内存,程序正常结束。
references:
类的深拷贝函数的重载
&&&&public class A
&&&&public:
&&&&&&&&...
&&&&&&&&A(A &a);//重载拷贝函数
&&&&&&&&A& operator=(A &b);//重载赋值函数
&&&&&&&&//或者 我们也可以这样重载赋值运算符 void operator=(A &a);即不返回任何值。如果这样的话,他将不支持客户代买中的链式赋值 ,例如a=b=c will be prohibited!
&&&&private:
&&&&&&&&int _
&&&&&&&&char *
A::A(A &a)
&&&&_id=a._
&&&&username=new char[strlen(a.username)+1];
&&&&if(username!=NULL)
&&&&&&& strcpy(username,a.usernam);
A& A::operaton=(A &a)
&&&&&&&&if(this==&a)//& 问:什么需要判断这个条件?(不是必须,只是优化而已)。答案:提示:考虑a=a这样的操作。
&&&&&&&&&&&&return *
&&&&&&&&if(username!=NULL)
&&&&&&&&&&&&
&&&&&&&&_id=a._
&&&&&&&&username=new char[strlen(a.username)+1];
&&&&&&&&if(username!=NULL)
&&&&&&&&&&& strcpy(username,a.usernam);
&&&&&&&&return *&&&&
//另外一种写法:
void A::operation=(A &a)
&&&&&&&&if(username!=NULL)
&&&&&&&&&&&&
&&&&&&&&_id=a._
&&&&&&&&username=new char[strlen(a.username)+1];
&&&&&&&&if(username!=NULL)
&&&&&&&&&&& strcpy(username,a.usernam);
其实,从上可以看出,赋值运算符和拷贝函数很相似。只不过赋值函数最好有返回值(进行链式赋值),返回也最好是对象的引用(为什么不是对象本身呢?note2有讲解), 而拷贝函数不需要返回任何。同时,赋值函数首先要释放掉对象自身的堆空间(如果需要的话),然后进行其他的operation.而拷贝函数不需要如此,因为对象此时还没有分配堆空间。
&&&&不要按值向函数传递对象。如果对象有内部指针指向动态分配的堆内存,丝毫不要考虑把对象按值传递给函数,要按引用传递。并记住:若函数不能改变参数对象的状态和目标对象的状态,则要使用const修饰符
note2:问题:
&&&&对于类的成员需要动态申请堆空间的类的对象,大家都知道,我们都最好要overload其赋值函数和拷贝函数。拷贝构造函数是没有任何返回类型 的,这点毋庸置疑。 而赋值函数可以返回多种类型,例如以上讲的void,类本身class1,以及类的引用 class &? 问,这几种赋值函数的返回各有什么异同?
&&&&答:1 如果赋值函数返回的是void ,我们知道,其唯一一点需要注意的是,其不支持链式赋值运算,即a=b=c这样是不允许的!
&&&&&&&&&&2 对于返回的是类对象本身,还是类对象的引用,其有着本质的区别!
&&&&&&&&&&&&&&第一:如果其返回的是类对象本身。
&&&A&operator&=(A&&a)
&&&&&&&&&&&&if(name!=NULL)
&&&&&&&&&&&&&&&&
&&&&&&&&this-&_id=a._
&&&&&&&&int&len=strlen(a.name);
&&&&&&&name=new&char[len+1];
&&&&&&&&strcpy(name,a.name);
&&&&&&&&return&*this;
&&&&&&&&&&其过程是这样的:
&&&&&&&&&&&&&&&&&&&&&&&class1 A("herengnag");
&&&&&&&&&&&&&&&&&&&&&&&&class1 B;&&&
&&&&&&&&&&&&&&&&&&&&&&&&B=A;
&&&&&&&&&&&&&&&&&&&&看似简单的赋值操作,其所有的过程如下:
&&&&&&&&&&&&&&&&&&&&&&&1&释放对象原来的堆资源
&&&&&&&&&&&&&&&&&&&&&&&2&重新申请堆空间
&&&&&&&&&&&&&&&&&&&&&&&3&拷贝源的值到对象的堆空间的值
&&&&&&&&&&&&&&&&&&&&&&&4&创建临时对象(调用临时对象拷贝构造函数),将临时对象返回
&&&&&&&&&&&&&&&&&&&&&&&5. 临时对象结束,调用临时对象析构函数,释放临时对象堆内存
my god,还真复杂!!
&&&&&&&&&&&&但是,在这些步骤里面,如果第4步,我们没有overload 拷贝函数,也就是没有进行深拷贝。那么在进行第5步释放临时对象的heap 空间时,将释放掉的是和目标对象同一块的heap空间。这样当目标对象B作用域结束调用析构函数时,就会产生错误!!
&&&&&&&&&&&&因此,如果赋值运算符返回的是类对象本身,那么一定要overload 类的拷贝函数(进行深拷贝)!
&&&&&&&&&&&&第二:如果赋值运算符返回的是对象的引用,
&&&A&&operator&=(A&&a)
&&&&&&&&&&&&if(name!=NULL)
&&&&&&&&&&&&&&&&
&&&&&&&&this-&_id=a._
&&&&&&&&int&len=strlen(a.name);
&&&&&&&name=new&char[len+1];
&&&&&&&&strcpy(name,a.name);
&&&&&&&&return&*this;
&&&&&&&&那么其过程如下:
&&&&&&&&&&&&&&&&&&&1 释放掉原来对象所占有的堆空间
&&&&&&&&&&&&&&&&&&&1.申请一块新的堆内存
&&&&&&&&&&&&&&&&&&&2 将源对象的堆内存的值copy给新的堆内存
&&&&&&&&&&&&&&&&&&&3 返回源对象的引用
&&&&&&&&&&&&&&&&&&&&4 结束。
&&&&因此,如果赋值运算符返回的是对象引用,那么其不会调用类的拷贝构造函数,这是问题的关键所在!!
完整代码如下:
//&virtual.cpp&:&Defines&the&entry&point&for&the&console&application.
#include&"stdafx.h"
#include&"string.h"
#include&"stdlib.h"
#include&"assert.h"
class&complex
&&&&&&&&int&
&&&&&&&&int&
&&&&complex(){real=virt=0;}
&&&&complex(int&treal,int&tvirt){real=virt=}
&&&&complex&operator+(const&complex&&x)
&&&&&&&&real+=x.
&&&&&&&&virt+=x.
&&&&&&&&return&*this;
&&&&complex&operator=(const&complex&&x)
&&&&&&&&return&complex(x.real,x.virt);
&&&&A(){m_username=NULL;printf("null&constructor");}
&&&&A(char&*username)
&&&&&&&&int&
&&&&&&&&len=strlen(username);
&&&&&&&&m_username=new&char[len+1];//(char*)malloc(sizeof(len+1));
&&&&&&&&strcpy(m_username,username);
&&&&&&&&printf(""nUsername&is&%s"n",m_username);
&&&&A(A&&a);
&&&&A&operator=(A&&b);
&&&&int&test(const&int&&x)
&&&&&&&&return&x;
&&&&virtual&~A()
&&&&//&&&&if(m_username)
&&&&&&&&delete&m_
&&&&&&&&printf(""nA&is&destructed"n");
protected:
&&&&char&*m_
A::A(A&&a)
&&&&int&len=strlen(a.m_username);
&&&&this-&m_username=new&char[len+2];
&&&&strcpy(m_username,a.m_username);
&&&&strcat(m_username,"f");
&&&&printf(""ndeep&copy&function");
A&A::operator=(A&&b)
&&&&if(m_username)
&&&&&&&&delete&m_
&&&&int&len=strlen(b.m_username);
&&&&this-&m_username=new&char[len+1];
&&&&strcpy(m_username,b.m_username);
//&&&&printf("copied&successfully!");
&&&&&return&*this;
class&B:public&A
&&&&B(char&*username,char&*password):A(username)
&&&&&&&&int&len=strlen(password)+1;
&&&&&&&&m_password=new&char[len];//(char&*)malloc(sizeof(len));
&&&&&&&&strcpy(m_password,password);
&&&&&&&&printf("username:%s,password:%s"n",m_username,m_password);
&&&&&&&&delete&m_
&&&&&&&&printf("B&is&destructed"n");
protected:
&&&&char&*m_
int&main(int&argc,&char*&argv[])
//&&&&B&b("herengang","982135");
//&&&&A&*a=&b;
//&&&&delete&a;
&&&&A&a("haha");
&&&&printf(""nbegin&to&invoke&copy&function");
//&&&&printf("%d",b.test(2));
&&&&//complex&x(1,3),y(1,4);
&&&&//x=(x+y);
&&&&//printf("%d,%d",x.real,x.virt);
&&&&return&0;
1 重载赋值运算符返回结果为类对象的运行结果
明显, 运算符最后调用了拷贝构造函数
2&重载赋值运算符返回结果为类对象引用的运行结果
很明显,没有调用拷贝构造函数
阅读(...) 评论()C++中拷贝构造函数的总结详解
字体:[ ] 类型:转载 时间:
深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝
1.什么是拷贝构造函数: 拷贝构造函数嘛,当然就是拷贝和构造了。(其实很多名字,只要静下心来想一想,就真的是顾名思义呀)拷贝又称复制,因此拷贝构造函数又称复制构造函数。百度百科上是这样说的:拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的参数(对象的引用)是不可变的(const类型)。此函数经常用在函数调用时用户定义类型的值传递及返回。2.拷贝构造函数的形式 代码如下:Class X{public:  X();  X(const X&);//拷贝构造函数}2.1为什么拷贝构造参数是引用类型?其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动被调用来生成函数中的对象(符合拷贝构造函数调用的情况)。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象,这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。3.拷贝构造函数调用的三种形式3.1.一个对象作为函数参数,以值传递的方式传入函数体;3.2.一个对象作为函数返回值,以值传递的方式从函数返回;3.3.一个对象用于给另外一个对象进行初始化(常称为复制初始化)。总结:当某对象是按值传递时(无论是作为函数参数,还是作为函数返回值),编译器都会先建立一个此对象的临时拷贝,而在建立该临时拷贝时就会调用类的拷贝构造函数。4.深拷贝和浅拷贝如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。(位拷贝又称浅拷贝,后面将进行说明。)自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。事实上这就要用到深拷贝了,要自定义拷贝构造函数。深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
下面举个深拷贝的例子。 代码如下:#include &iostream&class CA{public:  CA(int b,char* cstr)  {    a=b;     str=new char[b];    strcpy(str,cstr);  }  CA(const CA& C)  {    a=C.a;    str=new char[a]; //深拷贝    if(str!=0)     strcpy(str,C.str);  }  void Show()  {    cout&&str&&  }  ~CA()  {     } private:     char *};int main(){  CA A(10,"Hello!");  CA B=A;  B.Show();  return 0;}浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错。一定要注意类中是否存在指针成员。5.拷贝构造函数与“=“赋值运算符例如: 代码如下:class CExample{};int main(){CExample e1 = new CECExample e2 = e1;//调用拷贝构造函数CExample e3(e1);//调用拷贝构造函数CExample e4;e4 = e1;//调用=赋值运算符}通常的原则是:①对于凡是包含动态分配成员或包含指针成员的类都应该提供拷贝构造函数;②在提供拷贝构造函数的同时,还应该考虑重载"="赋值操作符号。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具Visual C++之赋值运算符“=”重载,以及深拷贝和浅拷贝
Visual C++之赋值运算符 = 重载,以及深拷贝和浅拷贝
在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。
如果对象在申明的同时马上进行初始化操作,则称之为拷贝运算。例如:
class1 A( af ); class1 B=A;
此时,其实际调用的是B(A)这样的浅拷贝操作。
如果对象在申明之后,再进行赋值运算,称之为赋值运算。例如:
class1 A( af ); class1 B;
此时,实际调用的是类的缺省赋值函数B.operator=(A);
不管是浅拷贝还是赋值运算,其都有缺省的定义。也就是说,即使我们不overload这两种operation,仍然可以运行。
那么,我们到底需不需要overload这两种operation呢?
答案就是:一般,如果需要手动编写析构函数的类,都需要overload拷贝函数和赋值运算符。
类的赋值运算符
1. C++中对象的内存分配方式
在C++中,对象的实例在编译的时候就需要为其分配内存大小。因此,系统都是在stack上为其分配内存的。这一点和C#完全不同!千万记住:在C#中,所有类都是referencetype,要创建类的实体,必须通过new在heap上为其分配空间,同时返回在stack上指向其地址的reference。
因此,在C++中,只要申明该实例,在程序编译后,就要为其分配相应的内存空间,至于实体内的各个域的值,就由其构造函数决定了。
A(int id,char *t_name)
name=new char[strlen(t_name)+1];
strcpy(name,t_name);
int main()
A a(1, herengang );
在程序编译之后,a和b在stack上都被分配相应的内存大小。只不过对象a的域都被初始化,而b则都为随机值。
其内存分配如下:
2. 缺省情况下的赋值运算符
如果我们执行以下:
则其执行的是缺省定义的缺省赋值运算。所谓缺省赋值运算,是指对象中的所有位于stack中的域,进行相应的复制。但是,如果对象有位于heap上的域的话,其不会为拷贝对象分配heap上的空间,而只是指向相同的heap上的同一个地址。
执行b=a这样的缺省的赋值运算后,其内存分配如下:
因此,对于缺省赋值运算,如果对象域内没有heap上的空间,其不会产生任何问题。但是,如果对象域内需要申请heap上的空间,那么在析构对象的时候,就会连续两次释放heap上的同一块内存区域,从而导致异常。
3. 解决办法:重载(overload)赋值运算符
因此,对于对象的域在heap上分配内存的情况,我们必须重载赋值运算符。当对象间进行拷贝的时候,我们必须让不同对象的成员域指向其不同的heap地址(如果成员域属于heap的话)。
因此,重载赋值运算符后的代码如下:
A(int id,char *t_name)
name=new char[strlen(t_name)+1];
strcpy(name,t_name);
A& operator =(A& a)
//注意:此处一定要返回对象的引用,否则返回后其值立即消失!
if(name!=NULL)
this-&_id=a._
int len=strlen(a.name);
name=new char[len+1];
strcpy(name,a.name);
cout&& ~destructor &&
int main()
A a(1, herengang );
其内存分配如下:
这样,在对象a,b退出相应的作用域时,其调用相应的析构函数,然后释放分别属于不同heap空间的内存,程序正常结束。
类的深拷贝函数的重载
public class A
A(A&a);//重载拷贝函数
A&operator=(A &b);//重载赋值函数
//或者,我们也可以这样重载赋值运算符 voidoperator=(A &a);即不返回任何值。如果这样的话,他将不支持客户代码中的链式赋值,例如a=b=cwill be prohibited!
A::A(A &a)
username=new char[strlen(a.username)+1];
if(username!=NULL)
strcpy(username,a.usernam);
A& A::operaton=(A &a)
if(this==&a)// 问:什么需要判断这个条件?(不是必须,只是优化而已)。答案:提示:考虑a=a这样的操作。
if(username!=NULL)
username=new char[strlen(a.username)+1];
if(username!=NULL)
strcpy(username,a.usernam);
//另外一种写法:
void A::operation=(A &a)
if(username!=NULL)
username=new char[strlen(a.username)+1];
if(username!=NULL)
strcpy(username,a.usernam);
其实,从上可以看出,赋值运算符和拷贝函数很相似。只不过赋值函数最好有返回值(进行链式赋值),返回也最好是对象的引用(为什么不是对象本身呢?note2有讲解),而拷贝函数不需要返回任何值。同时,赋值函数首先要释放掉对象自身的堆空间(如果需要的话),然后进行其他的operation而拷贝函数不需要如此,因为对象此时还没有分配堆空间。
注意事项1:
不要按值向函数传递对象。如果对象有内部指针指向动态分配的堆内存,丝毫不要考虑把对象按值传递给函数,要按引用传递。并记住:若函数不能改变参数对象的状态和目标对象的状态,则要使用const修饰符。
注意事项2:
对于类的成员需要动态申请堆空间的类对象,最好要overload其赋值函数和拷贝函数。拷贝构造函数是没有任何返回类型的,这点毋庸置疑。而赋值函数可以返回多种类型,例如以上讲的void,类本身class1,以及类的引用class&?
问:这几种赋值函数的返回各有什么异同?
答:1 如果赋值函数返回的是void,我们知道,其唯一一点需要注意的是,其不支持链式赋值运算,即a=b=c这样是不允许的!
2 对于返回的是类对象本身,还是类对象的引用,其有着本质的区别!
第一:如果其返回的是类对象本身。
A operator =(A& a)
if(name!=NULL)
this-&_id=a._
int len=strlen(a.name);
name=new char[len+1];
strcpy(name,a.name);
其过程是这样的:
class1 A( herengnag );
看似简单的赋值操作,其所有的过程如下:
1. 释放对象原来的堆资源;
2. 重新申请堆空间;
3. 拷贝源的值到对象的堆空间的值;
4. 创建临时对象(调用临时对象拷贝构造函数),将临时对象返回;
5. 临时对象结束,调用临时对象析构函数,释放临时对象堆内存。
但是,在这些步骤里面,如果第4步,我们没有overload拷贝函数,也就是没有进行深拷贝。那么在进行第5步释放临时对象的heap空间时,将释放掉的是和目标对象同一块的heap空间。这样当目标对象B作用域结束调用析构函数时,就会产生错误!!
因此,如果赋值运算符返回的是类对象本身,那么一定要overload类的拷贝函数(进行深拷贝)!
第二:如果赋值运算符返回的是对象的引用:
A& operator =(A& a)
if(name!=NULL)
this-&_id=a._
int len=strlen(a.name);
name=new char[len+1];
strcpy(name,a.name);
那么其过程如下:
1 释放掉原来对象所占有的堆空间
2.申请一块新的堆内存
3 将源对象的堆内存的值copy给新的堆内存
4 返回源对象的引用
因此,如果赋值运算符返回的是对象引用,那么其不会调用类的拷贝构造函数,这是问题的关键所在!!
完整代码如下:
// virtual.cpp : Defines the entry point for the console application.
class complex
complex(){real=virt=0;}
complex(int treal,int tvirt){real=virt=}
complex operator+(const complex &x)
complex operator=(const complex &x)
return complex(x.real,x.virt);
A(){m_username=NULL;printf( null constructor );}
A(char *username)
len=strlen(username);
m_username=new char[len+1];//(char*)malloc(sizeof(len+1));
strcpy(m_username,username);
Username is %s
,m_username);
A operator=(A &b);
int test(const int &x)
virtual ~A()
//if(m_username)
A is destructed
protected:
A::A(A &a)
int len=strlen(a.m_username);
this-&m_username=new char[len+2];
strcpy(m_username,a.m_username);
strcat(m_username, f );
deep copy function );
A A::operator=(A &b)
if(m_username)
int len=strlen(b.m_username);
this-&m_username=new char[len+1];
strcpy(m_username,b.m_username);
//printf( copied successfully! );
class B:public A
B(char *username,char *password):A(username)
int len=strlen(password)+1;
m_password=new char[len];//(char *)malloc(sizeof(len));
strcpy(m_password,password);
printf( username:%s,password:%s
,m_username,m_password);
printf( B is destructed
protected:
int main(int argc, char* argv[])
//B b( herengang ,
//A *a=&b;
A a( haha );
begin to invoke copy function );
//printf( %d ,b.test(2));
//complex x(1,3),y(1,4);
//x=(x+y);
//printf( %d,%d ,x.real,x.virt);
1 重载赋值运算符返回结果为类对象的运行结果
明显,运算符最后调用了拷贝构造函数。
2 重载赋值运算符返回结果为类对象引用的运行结果
很明显,没有调用拷贝构造函数。
Visual C++之赋值运算符“=”重载,以及深拷贝和浅拷贝由用户自行发布,Visual C++之赋值运算符“=”重载,以及深拷贝和浅拷贝内容不代表本站立场,请自行分辨真伪。

我要回帖

更多关于 重载拷贝构造函数 的文章

 

随机推荐