C++学习之路: class的this隐式指针讨论

class内部的成员函数是不需要把 自己的 privata元素传入的。因为系统已经通过this指针帮我们传入了。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 using namespace std;
 5 
 6 /*
 7  * 本例错误的原因是:set系列函数返回的是对象
 8  * 所以返回时产生了一个临时的对象
 9  */
10 class Student
11 {
12     public:
13         Student()
14             :id_(0), name_(""), age_(0)
15         {
16             cout << "构造Student" << endl;
17         }
18 
19         ~Student()
20         {
21             cout << "销毁Student" << endl;
22         }
23 
24 
25         Student setId(int id)
26         {
27             id_ = id;
28             return *this;
29         }
30 
31         Student setName(const string name)
32         {
33             name_ = name;
34             return *this;
35         }
36 
37         Student setAge(int age)
38         {
39             age_ = age;
40             return *this;
41         }
42 
43         void print(ostream &os) const
44         {
45             os << id_ << " " << name_ << " " << age_ << endl;
46         }
47 
48     private:
49         int id_;
50         string name_;
51         int age_;
52 };
53 
54 
55 int main(int argc, const char *argv[])
56 {
57     Student s;
58     s.setId(11).setName("zhangsan").setAge(88).print(cout);    //此处通过值拷贝返回了3个局部对象 {id_= 0, Name_ = "", age_ = 0}
59     s.print(cout);                                             //传入给setId() 返回一个拷贝 ①{id_= 11, Name_ = "", age_ = 0} 
60                                                                //传入给setName() 值拷贝返回一个局部对象②{id_= 11, Name_ = "zhangsan", age_ = 0} 
61                                                                //传入给setAge() 值拷贝返回一个局部对象③{id_= 11, Name_ = "zhangsan", age_ = 88} 
62                                                                
63 return 0; }
构造Student
11 zhangsan 88
销毁Student
销毁Student
销毁Student
11  0
销毁Student

//结果打印了销毁了3个局部变量

综上,如果不通过返回引用的方式return s,成员函数其实返回的是一个拷贝的副本, 上面我们已经分析过了一共调用了3次成员函数,共返回了3个局部对象,

分别是:

①{id_= 11, Name_ = "", age_ = 0}  是由setId()返回的一个副本
②{id_= 11, Name_ = "zhangsan", age_ = 0} 由setName()返回的一个副本
③{id_= 11, Name_ = "zhangsan", age_ = 88} 有setAge()返回的一个副本
 

##(参考《C与指针》)它们的作用域,是相继屏蔽的。作用域的知识可以参考c与指针

下面我们尝试使用返回引用的方式,让对象的成员函数返回自身的引用 的正确做法。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 using namespace std;
 5 
 6 /*
 7  * 本例演示了,this返回自身引用的正确做法
 8  *
 9  * 同时说明了重载print函数const版本的必要性
10  */
11 class Student
12 {
13     public:
14         Student()
15             :id_(0), name_(""), age_(0)
16         {
17             cout << "构造Student" << endl;
18         }
19 
20         ~Student()
21         {
22             cout << "销毁Student" << endl;
23         }
24 
25 
26         Student &setId(int id)
27         {
28             id_ = id;
29             return *this;
30         }
31 
32         Student &setName(const string name)
33         {
34             name_ = name;
35             return *this;
36         }
37 
38         Student &setAge(int age)
39         {
40             age_ = age;
41             return *this;
42         }
43 
44         const Student &print(ostream &os) const     //这一行,如果函数时const版本,那么返回值也必须是const 否则在语义上造成歧义, 编译器会报错
45         {
46             os << id_ << " " << name_ << " " << age_ << endl;
47             return *this;
48         }
49 
50         Student &print(ostream &os)    //此处重载了一个非const版本用于重载
51         {
52             os << id_ << " " << name_ << " " << age_ << endl;
53             return *this;
54         }
55 
56     private:
57         int id_;
58         string name_;
59         int age_;
60 };
61 
62 
63 int main(int argc, const char *argv[])
64 {
65     Student s;
66     s.setId(11).print(cout).setName("zhangsan").setAge(88).print(cout);
67     s.print(cout);
68     return 0;
69 }

上述代码我们演示了返回自身引用的 正确做法, 然而 在print打印函数,我们又重载了一个非const的版本,为什么要这么做呢?

我们知道, 当我们使用对象成员函数时, 如果传入的是一个const常量,那么该常量只能调用cons版本的函数进行处理, 

输入非常量时,则调用const 和 非const 版本都可以, 

const 的返回值依然还是const,有时我们不希望它返回一个const常量,而是希望返回一个变量 使得我们可以改变它, 

由此我们重载了一个非const版本。

原文地址:https://www.cnblogs.com/DLzhang/p/3985800.html