熟悉面向对象语言的读者一定对于
this 这个关键字很熟悉,比如Java中就有这一关键字,C++中也有,作用也和Java中的差不多。在这里我们简单介绍其概念和用法。
基本概念
The this pointer is a pointer accessible only within the nonstatic member functions of a class, struct, or union type. It points to the object for which the member function is called. Static member functions don’t have a this pointer.
注意以下几点:
- this 指针不是类的一部分,它不会影响 sizeof 语句的结果。
- this 指针用来指向调用非静态成员函数的对象(this被作为隐藏参数传递给非静态成员函数),当非静态成员函数被调用时,编译器会将该对象的地址作为隐藏参数传递给函数,为了理解这个概念我们可以看以下代码。
- ‘this’ pointer is not available in static member functions as static member functions can be called without any object (with class name).this指针在静态成员函数中是不可用的,因为静态成员函数不能用任何对象名调用。
myDate.setMonth( 3 );
上述调用语句相当于
setMonth( &myDate, 3 );
所以我们在成员函数中使用成员变量有以下三种方法
void Date::setMonth( int mn )
{
month = mn;
this->month = mn;
(*this).month = mn;
}
我们如果往深入想,为什么编译器会默认给成员函数传递 this 指针,这里引用一段GeeksforGeeks的相关内容。
To understand ‘this’ pointer, it is important to know how objects look at functions and data members of a class.
- Each object gets its own copy of the data member.
- All-access the same function definition as present in the code segment.
这里解释一下:**每个类都可以有多个对象,而每个对象都有各自的成员变量,彼此是独立的。而成员函数缺失所有对象共用的,即成员函数默认是内联的。那么当在成员函数中对成员变量进行操作时,CPU怎么知道要对那个对象的变量进行操作呢,因此这里的解决办法是,编译器默认将对象的地址传递给函数,这样就解决问题了。**编译器真是又当爹又当妈,一个人默默承担了所有,只为让程序员写代码写得爽。 到这里我们也就能理解 setMonth( &myDate, 3 ); 的真正含义了。
基本用法
注意点:this是不可变的,不能对其赋值。this的基本用法笔者总结下来有以下几点
- 返回对象本身
return *this - 防止自我调用
if (&Obj != this) 可以通过以下代码示例来了解上述用法
#include <iostream>
#include <string.h>
using namespace std;
class Buf
{
public:
Buf( char* szBuffer, size_t sizeOfBuffer );
Buf& operator=( const Buf & );
void Display() { cout << buffer << endl; }
private:
char* buffer;
size_t sizeOfBuffer;
};
Buf::Buf( char* szBuffer, size_t sizeOfBuffer )
{
sizeOfBuffer++;
buffer = new char[ sizeOfBuffer ];
if (buffer)
{
strcpy_s( buffer, sizeOfBuffer, szBuffer );
sizeOfBuffer = sizeOfBuffer;
}
}
Buf& Buf::operator=( const Buf &otherbuf )
{
if( &otherbuf != this )
{
if (buffer)
delete [] buffer;
sizeOfBuffer = strlen( otherbuf.buffer ) + 1;
buffer = new char[sizeOfBuffer];
strcpy_s( buffer, sizeOfBuffer, otherbuf.buffer );
}
return *this;
}
int main()
{
Buf myBuf( "my buffer", 10 );
Buf yourBuf( "your buffer", 12 );
myBuf.Display();
myBuf = yourBuf;
myBuf.Display();
}
注意点
为了加深理解,我们这里可以打印出this的值,可以看出其确实指向来对象的地址。
#include <iostream>
using namespace std;
class A {
int x;
public:
void show() {
cout << this << endl;
}
};
class B {};
class C {
char c;
};
int main() {
A *a1 = new A();
A *a2 = new A();
a1->show();
cout << a1 << endl;
a2->show();
cout << a2 << endl;
cout << sizeof(B) << endl;
cout << sizeof(C) << endl;
return 0;
}
output
0x7f8f86405a10
0x7f8f86405a10
0x7f8f86405a20
0x7f8f86405a20
1
1
另外,我们还想要注意:
- this 是 const 指针,它的值是不能被修改的,一切企图修改该指针的操作,如赋值、递增、递减等都是不允许的。
- this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的。
- 只有当对象被创建后 this 才有意义,因此不能在 static 成员函数中使用。
我们可以用以下代码来测试上述结论。 code1
#include<iostream>
using namespace std;
class Test
{
private:
int x;
public:
Test(int x = 0) { this->x = x; }
void change(Test *t) { this = t; }
void print() { cout << "x = " << x << endl; }
};
int main()
{
Test obj(5);
Test *ptr = new Test (10);
obj.change(ptr);
obj.print();
return 0;
}
上述代码会因为this->x = x 编译失败,因为不能this指针不能被修改过。
code2
#include<iostream>
using namespace std;
class Test {
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) {
this->x = x;
this->y = y;
}
static void fun1() { cout << "Inside fun1()"; }
static void fun2() {
cout << "Inside fun2()";
this->fun1();
}
};
int main() {
Test obj;
obj.fun2();
return 0;
}
以上代码也会编译失败,因为不能在静态成员函数中使用 this。
code3
#include<iostream>
using namespace std;
class Test {
private:
int x;
int y;
public:
Test (int x = 0, int y = 0) { this->x = x; this->y = y; }
Test setX(int a) { x = a; return *this; }
Test setY(int b) { y = b; return *this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
class B {
private:
int x;
int y;
public:
B(int x = 0, int y = 0) { this->x = x; this->y = y; }
B& setX(int a) { x = a; return *this;}
B& setY(int b) { y = b; return *this;}
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main() {
Test obj1;
obj1.setX(10).setY(20);
obj1.print();
Test obj2;
obj2.setX(10);
obj2.setY(20);
obj2.print();
cout << "===============================" << endl;
B b1;
b1.setX(10).setY(20);
b1.print();
B b2;
b2.setX(10);
b2.setY(20);
b2.print();
return 0;
}
运行结果在代码的注释中。上述代码涉及到this的一个重要用途:链式编程。但是我们在这里需要注意一点: **return *this 可以返回一个对象的拷贝,也可以返回一个对象的本身,这取决于函数返回体的定义。**因此我们在第一个实例中 obj1.setX(10).setY(20); 只能将obj1的x改为10,不能修改obj1.y,因为setX之后返回的是obj1的拷贝。
code4
#include<iostream>
using namespace std;
class Test {
private:
int x;
int y;
public:
Test(int x = 0, int y = 0) { this->x = x; this->y = y; }
void setX(int a) { x = a; }
void setY(int b) { y = b; }
void destroy() { delete this; }
void print() { cout << "x = " << x << " y = " << y << endl; }
};
int main() {
Test obj;
obj.destroy();
obj.print();
return 0;
}
上述代码可以编译成功,但是运行会出错,因为obj不是new的对象,所以该对象不能调用 delete this,只有new的对象才能调用 delete this。具体可以参考 Is it legal (and moral) for a member function to say delete this
Reference
- 《C++ Primer Plus 6th》
- this pointer
- ‘this’ pointer in C++
- C++ this指针详解
- C++day8 this指针(链式编程思想) 重要(注意看注释讲解)
|