在构造函数中,如果传进来的形参名字和成员名字一样,需要用this指针区分,否则无法赋值:
class Student { public: int id; Student(int id) { this->id = id; // 如果直接写成id = id,那么最终id还是0,即没有被赋值! } }
this指针,就是谁调用,指向的就是谁,比如:
Student s1(10);
在构造函数中,this指向的就是s1,所以,就是给s1的id成员赋值。
当然,最重要的是,this指针可是用来实现连锁调用:
class Student { public: int id; Student(int id) { this->id = id; } Student& id_plus1(Student& s) { // 连锁调用函数 id += s.id; return *this; } } int main() { Student s1(10); Student s2(0); s2.id_plus(s1).id_plus(s1); cout << s2.id << endl; }
上述结果输出为20,即让0加了两次0。在连锁调用函数中,函数返回了一个引用,传入的也是一个引用(注意,如果传入的不是引用,那会调用拷贝构造函数,但不影响结果)。由于返回的是一个引用,可以理解为还是s2自己,那么仍然可以继续调用,因此,实现了连锁调用。
当然,返回的不是引用也没有问题,返回一个指针也是可以的:
// 假设上述Student类中增加一个方法: Student* id_plus2(Student& s) { id += s.id; return this; // 返回的就是传入的对象的指针了,而不是对象本身 } // 然后再main函数里面这样写: Student s1(10); Student s2(0); s2.id_plus2(s1)->id_plus2(s1); cout << s2.id << endl; // 或者写成: Student s1(10); Student* s2 = new Student(0); s2->id_plus2(s1)->id_plus2(s1); cout << s2->id << endl;
上述输出的结果还是20,但原理不同,可以看到在连锁调用的时候,那个调用的”.“变成了”->“,就是因为第一次调用之后,返回的是一个指针,所以第二次调用的时候就要用箭头了。
值得注意的是,如果函数返回的既不是引用,也不是指针,那就有点意思了:
// 假设上述Student类中增加一个方法: Student id_plus3(Student& s) { id += s.id; return *this; } // 然后再main函数里面这样写: Student s1(10); Student s2(0); s2.id_plus3(s1).id_plus3(s1).id_plus3(s1); cout << s2.id << endl;
上述的输出结果是10,无论再连锁调用多少次id_plus3(s1),结果依然是10,因为每次返回来的对象,都可以理解为一个新创建的对象,那么,往后每次创建的对象,都是那个上次被新建的对象加10,而不是原来的s2加10,即等价于:
Student s1(10); Student s2(0); Student s3 = s2.id_plus3(s1); Student s4 = s3.id_plus3(s3); Student s5 = s3.id_plus3(s4); cout << s2.id << endl;
那么,真正作用于s2的加10,只有第一次!值得注意的是,s3-s5的创建,都是调用了拷贝构造函数!