歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C++拾遺--this指針

C++拾遺--this指針

日期:2017/3/1 9:32:55   编辑:Linux編程

前言

在用C++進行面向對象編程時,this指針是一個人盡皆知的東西。但我們真的清楚它嗎?下面我們對它的存在意義和使用方法一一進行探討。

this指針

存在意義:我們為何需要this指針?

看一個簡單的例子

#include <iostream>
using namespace std;

class MyClass
{
protected:
int a;
public:
MyClass(int a) :a(a)
{}
void setA(int a)
{
this->a = a;
}
int getA() const
{
return a;
}
};
int main()
{
MyClass my1(0);
MyClass my2(1);
my1.setA(2);
my2.setA(3);
cout << "my1::a = " << my1.getA() << endl;
cout << "my2::a = " << my2.getA() << endl;
cin.get();
return 0;
}

運行

這個例子實在是太簡單了!大家用腳指頭都能看明白。我們需要深入思考下:

1.setA方法中明明沒有this形參,為何在方法體中可以使用this?

答:this形參是隱式定義的,它代表當前對象的內存地址。我們不寫,並不代表它不存在。

2.在設計setA方法時,我故意把方法形參(int a)和類成員變量(int MyClass::a)設計成同名的。以至於function body中必須寫成 this->a=a;才能完成賦值。若把形參寫成不同名的,比如int A,是否可以省略this?

答:可以的。但本質上還是this->a=A;還是那句:我們不寫,並不代表它不存在。編譯器在進行編譯時,會自動把“a=A”改為“this->a=A;”。

3.從以上兩個問題還沒弄清this的存在意義嗎?那就多說一句,程序在內存中的存儲原理:代碼區是公共的,靜態變量是公共的。公共是只有一份的意思。

前者是公共的理由是:節約內存。後者是公共的理由是:邏輯上本該如此!(靜態變量的存在意義)

總之,類MyClass的任何對象在調用setA方法時,都是調用同一份代碼。但為何會有不同的效果呢?對象my1在調用setA時,是對my1.a進行賦值。對象my2在調用setA時,是對my2.a賦值。它們執行的代碼相同,卻不會亂掉,就是因為this指針的存在!

這就完了嗎?還沒有,我們需要進一步指出:this指針隱式定義於方法形參中。那麼它的位置是?這不好說,我的推測:就是第一個形參。我的理由:方法調用時,傳入的實參是從右向左入棧的,出棧時,第一個位置的參數當然就最先出棧。(若有不同的看法,歡迎討論!)以下的討論就暫且基於這種假設。

所以,setA(int a);本質上應該是 setA(MyClass * const this, int a);

my1.setA(2);本質上應該是 my1.setA(&my1, 2);

再深入,細心的你會發現,我寫的是 MyClass * const this,而不是 MyClass * this,多了一個const,為何?這當然也是有理由的!

理由很簡單:若this不是const的,則可以隨意更改this的指向,如下代碼:

void setA(int a)
{
this = &my;
this->a = a;
}

當然,這樣的代碼肯定是通不過編譯的。每次對setA的調用都變成了對my.a的賦值。

總結:默認情況下,this的類型是指向類類型非常量版本的常量指針。(《C++Primer》)

還沒完,我們還得繼續深入……

const成員函數是怎麼一回事?它和this有聯系嗎?

我們知道,const成員函數是不可以對成員變量進行修改的。那它是如何做到的呢?

原因:const對成員函數的修飾,就是對this的修飾。

上面的例子中的int getA()const;本質上是 int getA(MyClass const * const this);

至此,真相終於大白。

------------------------------分割線------------------------------

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

將C語言梳理一下,分布在以下10個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved