网站后台栏目发布,带孩子做网站,哈尔滨网站建设优化公司,模块化局域网网站建设软件一、对象的赋值
同类对象之间可以相互赋值#xff0c;对象赋值的一般形式#xff1a;对象名2 对象名1; 原理是#xff0c;赋值运算符的重载。仅赋值#xff0c;因此赋值前#xff0c;需要先定义并初始化对象2。
对象的赋值针对指对象中所有数据成员的值#xff1b; 对…一、对象的赋值
同类对象之间可以相互赋值对象赋值的一般形式对象名2 对象名1; 原理是赋值运算符的重载。仅赋值因此赋值前需要先定义并初始化对象2。
对象的赋值针对指对象中所有数据成员的值 对象的赋值只对其中的数据成员赋值不涉及成员函数。
#include iostream
#include sstream
using namespace std;class Student
{
public:Student(){num 0;}Student(int n, string na, char s){num n;name na;sex s;}void showinf( ){coutnum:num\tname:name\tsex:sexendl;}
private:int num;string name;char sex;
};int main()
{Student stud1(101,LL,m);//定义并初始化stud1调用Student(int n, string na, char s);Student stud2; //定义并初始化stud2调用Student();stud1.showinf();stud2.showinf();stud2stud1; //赋值运算符重载仅赋值操作因此之前应先定义并初始化stud2stud2.showinf();return 0;
}二、对象的复制
用已有的对象克隆出一个新对象对象复制的一般形式为:类名 对象2(对象1) 原理调用了编译系统提供的默认复制构造函数。
Student∷Student(const Student obj) //默认构造函数
{numobj.num;nameobj.name;sexobj.sex;
}
既定义又复制定义的同时执行复制对象操作不需要提前定义和初始化对象2
等价形式类名 对象2对象1;注注意区分对象赋值操作
#include iostream
#include sstream
using namespace std;class Student
{
public:Student(int n, string na, char s){num n;name na;sex s;}void showinf( ){coutnum:num\tname:name\tsex:sexendl;}
private:int num;string name;char sex;
};int main()
{Student stud1(101,LL,m);Student stud2(stud1); //等价于 Student stud2 stud1; 既是定义又是复制 定义复制stud2.showinf();return 0;
}三、复制构造函数
1、什么时候需要通过复制构造函数对对象进行复制
(1)新建立一个对象时直接利用复制构造函数进行定义和初始化Box box2(box1) (2)当函数的参数为类的对象调用函数时将实参对象完整地传递给形参通过调用复制构造函数来建立一个实参的拷贝
void fun(Box b){ }int main( )
{Box box1(12,15,18);fun(box1);return 0;
}
(3)函数的返回值是类的对象在函数调用完毕将函数中的对象复制一个临时对象并传给该函数的调用处。
Box fun( )
{Box box1(12,15,18);return box1;
}
int main( )
{Box box2;box2fun( );
}
2、复制构造函数的形式
复制构造函数的定义形式如下 类名(const 类名对象名) Time(const Time object); 3、浅复制
浅复制是指使用默的复制方式{类名 对象2(对象1)或 类名 对象2 对象1}方式复制数据成员的方式此种方式无法传递指针数据成员。
例1 当数据成员不包含指针时此种复制方式不会出现问题。
#include iostream
using namespace std;
class Test
{
private:int x;
public:Test(int n) {xn; }Test(const Test obj){xobj.x; }//复制构造函数void show (){coutxendl;}
};int main()
{Test test1(100);Test test2(test1); //对象复制形式一调用复制构造函数Test(const Test obj)Test test3test1; //对象复制形式二调用复制构造函数Test(const Test obj)test2.show();test3.show();return 0;
} 例2 当数据成员包含指针时此复制方式会由于指针的传递出现异常
#include iostream
using namespace std;
class Test
{
private:int x;char *pcr; //定义字符指针可指向字符串或字符数组
public:Test(int n, char* c) //初始化构造函数{xn;strcpy(pcr, c); //错误点这是一个野指针(但不是根源根源是复制的方式不对)}Test(const Test obj) //复制构造函数{xobj.x;strcpy(pcr, obj.pcr);}void show (){coutx:x\t pcr:pcrendl;}
};int main()
{Test test1(100,L); //初始化对象test1Test test2(test1); //对象复制形式一调用复制构造函数Test(const Test obj)Test test3test1; //对象复制形式二调用复制构造函数Test(const Test obj)test2.show();test3.show();return 0;
}
编译会报错。
4、深复制
深复制的目的先给包含指针的数据成员分配空间然后再去复制避免了指针数据成员存在野指针情况。
例3 在复制构造函数中预先为指针数据成员分配空间在析构函数中释放空间
#include iostream
using namespace std;
class Test
{
private:int x;char *pcr; //定义字符指针可指向字符串或字符数组
public:Test(int n, char* c) //初始化构造函数{xn;int m strlen(c)1; //C语言中的字符串结尾\0因此长度1pcr new char[m]; //为指针成员分配空间避免野指针strcpy(pcr, c); }Test(const Test obj) //复制构造函数{xobj.x;int m strlen(obj.pcr)1;pcr new char[m]; //为指针成员分配空间避免野指针strcpy(pcr, obj.pcr);}~Test(){delete pcr;} //由于构造函数中分配了空间因此必须在析构函数中释放void show (){coutx:x\t pcr:pcrendl;}
};int main()
{Test test1(100,Alibaba); //初始化对象test1Test test2(test1); //对象复制形式一调用复制构造函数Test(const Test obj)Test test3test1; //对象复制形式二调用复制构造函数Test(const Test obj)test2.show();test3.show();return 0;
} 例5 在复制构造函数中对指针数据成员直接传递【非常危险】
#include iostream
using namespace std;
class Test
{
private:int x;char *pcr; //定义字符指针可指向字符串或字符数组
public:Test(int n, char* c) //初始化构造函数{xn;pcr c; //直接传递指针地址貌似对一定有机会错}Test(const Test obj) //复制构造函数{xobj.x;pcr obj.pcr;}void show (){coutx:x\t pcr:pcrendl;}
};int main()
{Test *pt1;pt1 new Test(100,GW);Test test2(*pt1);Test test3 (*pt1);test2.show();test3.show();delete pt1;test2.show();test3.show();return 0;
} 注意虽然通过传递指针的方式实现了对象的复制。但是当Test *pt1被释放掉时由pt1复制产生的test2和test3的数据成员中的指针数据成员所指向的内存空间可能不变也可能改变。 上图程序运行的结果是释放后此段内存空间没变但实际程序运行中则不一定。 所以直接传递指针的方式非常危险