深入探讨this指针 为了写这篇文章,准备了好长时间,翻遍了箱底的书籍。但是现在还是不敢放开手来写,战战兢兢。不是担心自己写错,而是唯恐自己错误误导别人。同时也希望这篇文章能给你一点收获。既然是深入探讨this指针,所以建议初学者,最好具有一定编译基础,调试基础。如果大家认为这片文章有不满的地方,就给我发信批评一下,以便及时修正。 关于this指针的描述我们一般从语言层次上讲; this指针作为一个隐含参数传递给非静态成员函数,用以指向该成员函数所属类所定义的对象。当不同的对象调用同一个类的成员函数代码时,编译器会依据该成员函数的this指针所指向的不同对象来确定应该引用哪个对象的数据成员。简单例子 我们定义一个简单stack类 // 定义stack类 class Stack { public: Stack();// 构造函数 ~Stack();// 析构函数 public: void push(char c);// 压栈函数 private: char *top;// 栈顶元素 char *max;// 栈容量 }; // 压栈函数 void Stack::push(char c) { if(top > max) { ERROR; } *top++ = c; } // 定义公共函数,操作栈对象中的push函数 void FunStack(Stack *p) { p->push('c'); } 上面的代码我们加入this概念,以C代码形式显示(你可以理解编译C++成C代码后,Cfront开始就是这么做的) // 用普通C描述类成员函数 void Stack__push(this,c);// 普通C代码 { if(this->top > this->max) { ERROR; } *(this->top)++ = c; } void FunStack(p)// Stack *p; { Stack__push(p,'c'); } C++中this指针是从Simula(只是听说没有使用过)里的THIS引用的翻版,有时候有人会问,为什么this是指针而不是一个引用?为什么叫this而不是叫self(smalltalk)?第一个问题是,当this引入带类的C时,在那时的是C++中还没有引用机制,所以只能是this指针而不是引用了。第二个问题,更简单了,就是因为this是从simula来,而不是从smalltalk来。 上面是简单的讨论,我们将逐步深入讨论this。 我们通过this访问对象(已经成惯例了)中函数和变量时一般这样使用 this->top;// 访问变量 this->push();// 访问函数 (*this).top;// 访问变量 (*this).push();// 访问函数 通过上面例子,我们从语言层次上说this是一个指针(也许你说this本来就是一个指针,就叫this指针,不要着急听我慢慢说来)。那么this是一个什么样子的指针,比如我们最常见的指针有。 int *p; Const int *p; int * const p; 那么this指针是不是其中一种?下面我们分别验证。 我们定义类,作为验证对象 class A { public: int iData;// 简单期间我们定义为int型 mutable int iData2;// mutable变量 int Fun1(){return ++iData;};// 普通函数㈠ int Fun2() const {return ++iData;};// 带const的函数㈡ }; 上面的㈠函数可以正确执行。 上面㈡函数,不能通过编译,我们知道在const函数中,不允许修改类中变量。那么最终原因是什么?其实在上面的例子中,我们用C实现 int A_Fun2(const A* this); const函数本质是const this的原因,所以不允许修改iData值。 至少现在我们可以确定this指针,不是一个const常量指针。因为如果this是常量指针,我们就不能修改类中变量的值了。捎带我们提一下C++中关键字mutable,如上定义的mutable int iData2;// mutable变量,这样我们就可以在const函数中修改iData2的值。其实这时的mutable和public,private,protected是相同的,这些关键字只是在编译时刻有用,编译后变量类型是没有区别的。更深一步说,强制类型转换也是对编译器来说,是通过编译器编译过程中判断类型转换的正误。 那么this对象是否是A *const this的值哪?首先我们先看一个例子 static int iTest = 1; class A { public: int iData;// 简单期间我们定义为int型 mutable int iData2;// mutable变量 int Fun1() { int iTemp = 4; |