::  ::  ::  ::  :: 管理

C++中this指针的理解和用法

Posted on 2008-06-16 05:17 nt05 阅读(443) 评论(0)  编辑 收藏 引用 所属分类: cpp

先要理解class的意思。class应该理解 为一种类型,象int,char一样,是用户自定义的类型。(虽然比int char这样build-in类型复杂的多,但首先要理解它们一样是类型)。用这个类型可以来声明一个变量,比如int x, myclass my等等。这样就像变量x具有int类型一样,变量my具有myclass类型。
理解了这个,就好解释this了,my里的this 就是指向my的指针。如果还有一个变量myclass mz,mz的this就是指向mz的指针。 这样就很容易理解this 的类型应该是myclass *,而对其的解引用*this就应该是一个myclass类型的变量。
通常在class定义时要用到类型变量自身时,因为这时候还不知道变量名(为了通用也不可能固定实际的变量名),就用this这样的指针来使用变量自身。

1 . this 指针的用处 :
一 个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态 成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的, 它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。
例如,调用date.SetMonth(9) <===> SetMonth(&date, 9),this帮助完成了这一转换
.
2. this 指针的使用 :
种情况就是,在类的非静态成员函数中返回类对象本身的时候,直接使用 return *this;另外一种情况是当参数与成员变量名相同时,如this->n = n (不能写成n = n)。
3. this 指针程序示例 :
this指针是存在与类的成员函数中,指向被调用函数所在的类实例的地址。
根据以下程序来说明this指针
#include<iostream.h>
class Point
{
    int x, y;
public:
    Point(int a, int b) { x=a; y=b;}
    Void MovePoint( int a, int b){ x+=a; y+=b;}
    Void print(){ cout<<"x="<<x<<"y="<<y<<endl;}
};
void main( )
{
     Point point1( 10,10);
     point1.MovePoint(2,2);
     point1.print( );
}
当对象point1调用MovePoint(2,2)函数时,即将point1对象的地址传递给了this指针。
MovePoint函数的原型应该是 void MovePoint( Point *this, int a, int b);第一个参数是指向该类对象的一个指针,我们在定义成员函数时没看见是因为这个参数在类中是隐含的。这样point1的地址传递给了this,所以在 MovePoint函数中便显式的写成:
void MovePoint(int a, int b) { this->x +=a; this-> y+= b;}
即可以知道,point1调用该函数后,也就是point1的数据成员被调用并更新了值。
即该函数过程可写成 point1.x+= a; point1. y + = b;
4. 关于 this 指针的一个精典回答 :
当你进入一个房子后,
你可以看见桌子、椅子、地板等,
但是房子你是看不到全貌了。

对于一个类的实例来说,
你可以看到它的成员函数、成员变量,
但是实例本身呢?
this是一个指针,它时时刻刻指向你这个实例本身。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

它实际上是类定义中一个缺省的预定义的指针。当调用一个成员函数时,系统保证this 指针始终指向产生这个调用的对象,并将该指针作为一个变元自动传递给该函数。同时,只有对象和成员函数之间才存在 this 指针。

【示例】下面一段程序创建一个叫做power的类来计算一个数的幂:

power
{
    private:
    double b, val;
        int e;
public:
    power(double base, int exp);
    double get_power() { return val;}
};
power::power(double base ,int exp)
{
   b = base;
   e = exp;
   val = 1;
   if(exp == 0)
     return;
   for(; exp > 0; exp--)
     val = val * b;}
void main()
{
   power x(4.0, 2), y(2.5, 1), z(5.7, 0);
      cout << x.get_power() <<"";
   cout << y.get_power() <<"";
      cout << z.get_power() <<"\n";
}

在一个类的成员函数内部(如power()),可以直接引用一个类的数据成员,而无需用任何对象或类的限制性说明。所以在 power 类的构造函数 power() 里语句b = base; 意味着参数 base 的值将被赋予产生这个调用的对象中的数据成员 b。在程序中分别定义了 power 的三个对象 x、y 和z,编译器将对象的成员函数与同一对象的数据成员在调用时联系在一起,为此编译器实际上给成员函数传递了一个隐藏的指向函数调用所要引用的对象的指针, 即 this 指针。相同的语句可以改写如下:

    this->b = base;

    这表明,当发生函数调用时(例如当新建一个 power 类的对象x时),编译器传给构造函数 power() 一个指向对象 x 的 this 指针,并隐式地使用这个指针访问属于对象x的b的拷贝。其实上述 power() 函数中的 b=base 等语句只是简写形式,下面是用 this 指针改写的完整的 power()函数:

power::power(double base , int exp)
{
    this->b = base;
this->e = exp;
    this->val = 1;
if(exp == 0) return;
for(; exp>0; exp--)
    this->val = this->val*this->b;
}

    在这个例子中,数据成员的名字前缀表达式 this-> 是合法的但没有什么效果,因为this 指针的使用本来就是隐式的。友元函数不是类的成员,而且没有this指针,静态成员函数也没有 this 指针。但在另一些情况下,必须用 this 指针明确当前调用的对象,如在重载运算符时,可以看到 this 指针是非常重要的,它在某些类型的链表管理中往往也是必要的

----------------------------------------------------------------------------------------------------------
this在成员函数的开始前构造,在成员的结束后清除。
这个生命周期同任何一个函数的参数是一样的,没有任何区别。
因为,成员函数默认第一个参数就是this。
举例:
class A{
public:
int func(int p){}
};
func的原型在编译器看来,应该是
int func(A* const this, int p);

即开始执行成员函数之前,构造。
成员函数执行结束,清除。

如果class或者struct里没有成员函数,this是没有构造函数的。只能当作C的STRUCT使用
当调用一个成员函数时,系统保证this 指针始终指向产生这个调用的对象,并将该指针作为一个变元自动传递给该函数。同时,只有对象和成员函数之间才存在 this 指针。

VC 里的this指针在成员函数调用的时候,是保存在ecx寄存器里的,函数调用时mov指针内容到寄存器,而不是将其作为某个参数压栈。另外,由于成员函数 需要一个隐藏的this指针参数,而且调用的压栈方式不符合回调函数的约定,所以不能用来作回调函数。类内的static函数可以用作回调,因为它不能访 问非static成员变量。