this指针简单来说:通过对象来调用一个非静态成员函数,那个对象的地址就是this。this是隐含在每一个非静态成员函数的内部的指针常量。

 1 class CDocument
 2  {
 3  public:
 4      void onFileOpen()
 5      {
 6 
 7          first();
 8          second();
 9          Serialize();//动态变化的部分
10          last();
11 
12      }
13          virtual ~CDocument() {}
14 protected:
15          virtual void Serialize() = 0;
16          void first();
17          void second();
18          void last();
19      };
20 
21  void CDocument::first() { cout << "dialog..." << endl; }
22  void CDocument::second() { cout << "check file..." << endl; }
23  void CDocument::last() { cout << "close file..." << endl; }
24  //application
25  class CMyDoc :public CDocument
26  {
27  public:
28          void Serialize() //子类重写
29              {
30                  cout << "CMyDoc::serialize..." << endl;
31              }
32      };
33  int main()
34  {
35          CMyDoc mydoc;
36          mydoc.onFileOpen(); //子类对象调用父类函数
37  }

  以上第36行可以理解为:mydoc.onFileOpen(&mydoc),this指向这个对象的地址,接着就把this指针传递给 了onFileOpen()。

1  void CDocument::onFileOpen()
2      {
3 
4          this->first();
5          this->second();
6          this-> Serialize(); //动态绑定
7          this->last();
8 
9      }

  由于this是一个向上转型后的指针,父类指针指向子类对象,并且在第6行调用虚函数,于是编译器就把第6行转变成(*this->vptr[n])(this),所以会调用子类的虚函数。

  这里的vptr是一个虚函数指针,指向虚函数表,表中是类的虚函数地址。当父类写了一个虚函数时,父类内部就多了一个虚函数指针(vptr),这个指针指向它的虚函数表,表中存放的是函数的入口地址(比如serialize()),当子类继承父类时,会把父类中的虚函数指针继承下来,指向子类的虚函数表。(此时虚函数表中的地址和父类的虚函数地址一样)当子类重写了父类的虚函数时,子类就会把虚函数表中函数地址替换成自己重写的虚函数地址。当发生动态绑定(三个条件:1、是指针调用2、是一个向上转型的指针3、调用虚函数),编译器就会把第6行转变成(*this->vptr[n])(this),调用子类重写的虚函数。