1 問題的提出:this指針解決的是什麼問題?
在上一講 C++學習(二):類的定義與對象的創建 中,我們提到了類與對象,那麼類是怎麼進行數據存儲的呢?
類是將數據分爲Data和Function兩部分來存儲的,比如同樣的CGoods類,其Data部分是不同對象單獨存儲,而Function部分是放在一起來調用的。
但這樣會有一個問題,我們在實例化以後,如果給不同的對象賦值,比如下面代碼中給CGoods實例化爲c1和c2,我們的函數 GetName 怎麼能知道調用的是誰的 name呢?誠然,我們是在代碼中以c1. c2.爲前綴說明了應該調用誰的name,所以我們要探究的就是這種機制,看看是怎麼運行的。this指針就是解決的這個問題。
這裏老師說的有些亂,我按我的理解大體總結成上面的話,但也有些混亂,不知道老師具體想表達啥意思,我覺得都已經拿c1,c2調用了,函數肯定知道到底是誰的name了吧…好在這裏不太理解無傷大雅。
class CGoods
{
public: //給用戶提供的方法,哪些操作
void RegisterGoods(char name[],int amount,float price); //輸入數據
{
strcpy(Name,name); //複製字符串strcpy(dst,src)
Amount = amount;
Price = price;
}
void CountTotal(void); //計算商品總價值
{
Total_value = Amount * Price;
}
void GetName(char name[]); //讀取商品名
{
strcpy(name,Name);
}
int GetAmount(void); //讀取商品數量
{
return Amount;
}
float GetPrice(void); //讀取商品單價
{
return Price;
}
float GetTotal_value(void);
{
return Total_value;
}
private: //有哪些成員(可操作的變量)
char Name[21];
int Amount;
float Price;
float Total_value;
};
void main()
{
CGoods c1,c2; //定義對象——過程就是實例化
c1.RegisterGoods("C++",10,45);
c2.RegisterGoods("Java",5,43);
char name[20];
c1.GetName(name);
cout<<name<<end1;
c2.GetName(name);
cout<<name<<end1;
}
2 this指針
首先,在類中的函數定義以後,this指針就被隱藏定義了,this表示的是當前的對象。
我們先來看C語言中學生結構體的一個例子:
struct Student
{
char name[10];
int age;
char sex[3];
};
void InitStu(Student *st, char n[10], int a, char s[3])
{
strcpy(st->name,n);
st->age = a;
strcpy(st->sex,s);
}
void main()
{
Student st1,st2,st3; //定義三個對象
InitStu(&st1, "大明", 20, "男");
InitStu(&st2, "小紅", 18, "女");
InitStu(&st3, "老郭",30,"男");
}
其中的指針st就類似於this指針,指明是哪個對象被調用。換作我們之前的CGoods類,可以看到其實在定義對象以後,原函數在被調用時,已經使用了this指針,只不過將其隱藏了。
我們特意將RegisterGoods裏的參數全換成大寫的,與類參數定義的一致,則需要靠this函數指明哪一個是底下c1,c2對象的,哪一個是上面參數指代的。
class CGoods
{
public: //給用戶提供的方法,哪些操作
void RegisterGoods(char Name[],int Amount,float Price); //輸入數據
{
//this
strcpy(this->Name,name); //複製字符串strcpy(dst,src)
this->Amount = Amount;
this->Price = Price;
}
...
private: //有哪些成員(可操作的變量)
char Name[21];
int Amount;
float Price;
float Total_value;
};
void main()
{
CGoods c1,c2; //定義對象——過程就是實例化
c1.RegisterGoods("C++",10,45);
c2.RegisterGoods("Java",5,43);
char name[20];
c1.GetName(name);
cout<<name<<end1;
c2.GetName(name);
cout<<name<<end1;
}
而從上面的過程,我們可以看出C++內部編譯時在使用類時的識別過程。第一步先識別類名,即CGoods;第二步再識別數據成員,無論公有私有;第三步纔是識別函數和改寫函數的過程。
在第三步中,實際編譯上程序使用的是註釋部分:
class CGoods
{
public:
//void RegisterGoods(CGoods *const this, char Name[], int Amount, int Price)
void RegisterGoods(char Name[],int Amount,float Price); //輸入數據
{
strcpy(this->Name,name);
this->Amount = Amount;
this->Price = Price;
}
...
//void CountTotal(CGoods *this)
void CountTotal();
...
void main()
{
CGoods c1,c2;
//RegisterGoods(&c1,"C++",10,12);
c1.RegisterGoods("C++",10,12);
//RegisterGoods(&c2,"Java",5,20);
c2.RegisterGoods("Java",5,20);
char name[20];
//GetName(&c1,name);
c1.GetName(name);
cout<<name<<end1;
}
3 補充:關於const
int a = 10; int b = 20
const int *p = &a ;
int * const p = &a ;
const int * const p = &a ;
以上三種,就像換男朋友和花錢一樣。
第一種 const int *p = &a,不能換指向空間中的數據,但可以換指向空間。比如現在p指向的是a,a=10,我們不能讓a=20,但我們可以讓p指向另一個b,b=20。
第二種 int * const p = &a, const在星號右邊,不能換指向空間,但可以換數據。
第三種const int * const p = &a ;既不能更改數據,也不能更改指向空間。