首页 > 编程语言 >C++快速入门 第三十六讲:副本构造器

C++快速入门 第三十六讲:副本构造器

时间:2023-08-18 15:36:26浏览次数:38  
标签:副本 int rhs C++ 构造 MyClass 第三十六 ptr

我们可以把一个对象赋值给一个类型与之相同的变量,编译器将生成必要的代码把“源”对象各属性的值分别赋值给“目标”对象的对应成员。这种赋值行为称之为逐位复制。(但如果某些成员变量是指针的话,对象成员逐位复制的结果是你将拥有两个一模一样的实例,而这两个副本里的同名指针会指向相同的地址)

实例1:带指针变量的等号重载

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 class MyClass
 6 {
 7 public:
 8     MyClass(int *p);//构造器
 9     ~MyClass();//析构器
10     
11     MyClass &operator = (const MyClass &rhs);//运算符(=)重载 
12     void print();//打印 
13 private:
14     int *ptr; 
15 };
16 
17 MyClass::MyClass(int *p)//构造器实现 
18 {
19     ptr = p;
20 }
21 
22 MyClass::~MyClass()//析构器实现 
23 {
24     delete ptr;
25  } 
26  
27 // a = b; 如obj1 = obj2; 
28 MyClass &MyClass::operator=(const MyClass &rhs)//运算符(=)重载实现,rhs为另一对象 
29 {
30     if(this != &rhs)//obj1不等于obj2时,this指针指的是指向当前类生成的对象(此处指第一个MyClass) 
31     {
32         delete ptr;//删除地址ptr,释放obj1的内存 
33         
34         ptr = new int;//创建新的内存给指针ptr 
35         *ptr = *rhs.ptr;//解引用,将obj2的值赋值给obj1 
36         //cout << "复制指针!\n";
37     }
38     else
39     {
40         cout << "赋值号两边为同个对象,不做处理!\n";//obj1 = obj2时 
41     }
42     return *this;//返回第一个MyClass对象 
43 }
44 
45 void MyClass::print()//打印*ptr的值 
46 {
47     cout << *ptr << endl;
48 }
49 
50 int main()
51 {
52     MyClass obj1(new int(1));//创建对象obj1 
53     MyClass obj2(new int(2));//创建对象obj2
54     
55     obj1.print();//打印对象obj1中指针指向的地址的储存值 
56     obj2.print();//打印对象obj2中指针指向的地址的储存值 
57     
58     obj2 = obj1;//obj1通过等号重载给obj2 
59     
60     obj1.print();//打印对象obj1中指针指向的地址的储存值 
61     obj2.print();//打印对象obj2中指针指向的地址的储存值 
62     
63     return 0;
64 }

实例2:副本构造器

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 class MyClass
 6 {
 7 public:
 8     MyClass(int *p);//主构造器
 9     MyClass(const MyClass &rhs);//副本构造器 
10     ~MyClass();//析构器
11     
12     MyClass &operator = (const MyClass &rhs);//运算符(=)重载,对象复制,括号里声明对象调用副本构造器 
13     void print();//打印 
14 private:
15     int *ptr; 
16 };
17 
18 MyClass::MyClass(int *p)//主构造器实现 
19 {
20     cout << "进入主构造器\n"; 
21     ptr = p;
22     cout << "离开主构造器\n";
23 }
24 MyClass::MyClass(const MyClass &rhs)//副本构造器实现 
25 {
26     cout << "进入副本构造器\n"; 
27     *this = rhs; //等号赋值重载 
28     cout << "离开副本构造器\n";
29 }
30 
31 MyClass::~MyClass()//析构器实现 
32 {
33     cout << "进入析构器\n";
34     delete ptr;
35     cout << "离开析构器\n"; 
36 } 
37  
38 // a = b; 如obj1 = obj2; 
39 MyClass &MyClass::operator=(const MyClass &rhs)//运算符(=)重载实现,rhs为另一对象 
40 {
41     cout << "进入赋值语句重载\n";
42     if(this != &rhs)//obj1不等于obj2时,this指针指的是指向当前类生成的对象(此处指第一个MyClass) 
43     {
44         delete ptr;//删除地址ptr,释放obj1的内存 
45         
46         ptr = new int;//创建新的内存给指针ptr 
47         *ptr = *rhs.ptr;//解引用,将obj2的值赋值给obj1 
48         //cout << "复制指针!\n";
49     }
50     else//obj1与obj2为同一个对象时 
51     {
52         cout << "赋值号两边为同个对象,不做处理!\n"; 
53     }
54     cout << "离开赋值语句重载\n";
55     return *this;//返回第一个MyClass对象 
56 }
57 
58 void MyClass::print()//打印*ptr的值 
59 {
60     cout << *ptr << endl;
61 }
62 
63 int main()
64 {
65     MyClass obj1(new int(1));//创建对象obj1 
66     MyClass obj2(new int(2));//创建对象obj2
67     obj2 = obj1;//obj1通过等号重载给obj2
68     obj1.print();//打印对象obj1中指针指向的地址的储存值 
69     obj2.print();//打印对象obj2中指针指向的地址的储存值 
70     
71     cout << "---------------------------------------------\n"; 
72     
73     MyClass obj3(new int(3));//创建对象obj3
74     MyClass obj4 = obj3;//副本构造器 
75     obj3.print();//打印对象obj3中指针指向的地址的储存值 
76     obj4.print();//打印对象obj4中指针指向的地址的储存值 
77     
78     cout << "---------------------------------------------\n"; 
79     
80     MyClass obj5(new int(5));//创建对象obj5
81     obj5 = obj5;
82     obj5.print();//打印对象obj5中指针指向的地址的储存值 
83     
84     return 0;
85 }

标签:副本,int,rhs,C++,构造,MyClass,第三十六,ptr
From: https://www.cnblogs.com/ybqjymy/p/17640639.html

相关文章

  • C++快速入门 第三十八讲:避免内存泄漏
    如果程序会运行很长时间(例如在服务器上,注意不是所有的操作系统都像windows一样每天都要重启),并且在不停地申请新的内存块,忘记释放那些已经不再有用的老内存迟早会把内存消耗殆尽,直接导致后边的new操作无法执行甚至崩溃。动态内存是没有作用域的,所以必须由程序员来跟踪它们......
  • C++快速入门 第三十七讲:高级强制类型转换
    实例1:静态强制转换1#include<iostream>2#include<string>34usingnamespacestd;5classCompany6{7public:8Company(stringtheName,stringproduct);9virtualvoidprintInfo();1011protected:12stringname;13......
  • C++快速入门 第二十七讲:运算符左移<<重载
    一般来说,在调用operator<<()重载函数时,传递给它的是哪一个流,它返回的就应该是那个流的一个引用。实例:左移操作符重载1#include<iostream>2#include<string>3#include<math.h>45usingnamespacestd;6classRational//定义基类7{8public:......
  • C++快速入门 第二十八讲:多继承(multiple inheritance)
    1多继承语法:23//助教类既继承于老师类,又继承于学生类4classAssistant:publicTeacher,publicStudent5{6};78当遇到的问题无法只用一个“是一个”关系来描述的时候,就是多继承出场的时候。例即是学生,又是人,还是助教。910#include<iostre......
  • C++快速入门 第三十讲:错误处理和调试
    程序出错可以分为两大类:编译时出错(complie-timeerror)和运行时错误(run-timeerror)suggest1:培养并保持一种编程风格suggest2:认真对待编译器给出的错误/警告信息suggest3:写代码三思而后行(先画流程图)suggest4:注意检查最基本的语法suggest5:把可能有问题的代码行注释suggest......
  • C++快速入门 第二十九讲:虚继承
    通过虚继承某个基类,就是在告诉编译器:从当前这个类再派生出来的子类只能拥有那个基类的一个实例。虚继承的语法:1classTeacher:virtualpublicPerson23{45}这样做的话便可以让Student和Teacher类都虚继承自Person类,编译器将确保从Student和Teacher类再派生出来的子......
  • C++快速入门 第三十一讲:错误处理与调试2
    让函数返回错误代码实例:范围限制1#include<iostream>2#include<climits>34usingnamespacestd;5classFactorial6{7public:8Factorial(unsignedshortnum);9unsignedlonggetFactorial();10boolinRange();1112private......
  • C++快速入门 第三十二讲:assert函数和捕获异常
    C语言和C++都有一个专门为调试而准备的工具函数---assert函数。这个函数是在assert.h库文件里定义的。实例1:assert函数应用1#include<cassert>2//assert()函数需要有一个参数,它将测试这个输入参数的真或者假状态3//如果为真Donothing4//如果为假Dosomething......
  • C++快速入门 第十八讲:访问控制
    访问控制:C++提供用来保护(保护意思是对谁可以调用某个方法和访问某一个属性加上一个限制)类里的方法和属性的手段实例1:访问级别应用1//级别允许谁来访问2//public任何代码3//protected这个类本身和它的子类4//private只有......
  • C++无法将类的成员函数赋值给一般的函数指针,解决方案
    遇到需要绑定回调函数的API接口。看了定义的函数指针,是静态的函数指针,将非静态的类成员函数赋值过去的时候,无法编译通过。将成员函数改成静态又得将整个类的内容都改成静态。这种情况下,可以构造匿名函数,引用this,这样可以在类中,将自己的成员函数赋值给需要的函数指针类型上:ser......