程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++模板:名稱查找

C++模板:名稱查找

編輯:C++入門知識

C++模板:名稱查找


在編譯模板的時候,編譯器會分兩個階段去解析遇到的名稱,第一個階段解析不依賴於模板參數的名稱,第二個階段解析依賴於模板參數的名稱,下面舉個簡單的例子來說明這一點:

template class X {
public:
	typedef int E;
};

typedef double E;

template class Y : public X {
public:
	E f() {}
};
這個例子中定義了兩個類模板,其中Y派生於X,在X中我們給int取了個別名E,接著在全局作用域中給double也取了個別名E,在Y中有一個函數f(),它的返回值類型為E,那麼這個E到底是double呢,還是int?結果是double,因為f()不依賴與模板參數T,所以它在第一階段就會被解析,而它的基類X<.T>在第二階段才會被解析,所以解析f()的時候只能看到全局作用域裡的typedef double E。如果大家心裡有疑問,我們可以看看非模板類的情況:

class X {
public:
	typedef int E;
};

typedef double E;

class Y : public X {
public:
	E f() {}
};

int main(){

	Y y;
	cout<這個例子中都是普通的類,通過main函數的測試,可以看到f()的返回類型變成了int。接下來我們再來看一個例子:

void g() { cout<<"gobal::g()"< class X {
public:
	typedef int E;
	void g() { cout<<"X::g()"< class Y : public X {
public:
	E f() { g(); this->g(); }
};

int main(){

	Y y;
	cout<這個例子中首先定義了一個全局函數g(),接著定義了類模板X,在X中定義了一個成員函數g(),類模板Y依然繼承於X,在Y中的f()中“以兩種方式”調用了g(),那麼這兩種方式調用的是同一個g()嗎?答案是:不是,第一種方式調用了全局的g(),而第二種方式調用了基類的g(),原因在於當編譯器遇到第一種方式的g()時,發現它沒有表現出要依賴於模板參數,所以認為它不依賴於模板參數,因而在第一階段就進行了解析,此時X尚未解析,所以g()是全局的g(),通過第二種方式調用時,用this指針指出g()是依賴於當前對象的,也就依賴於模板參數,因而會在第二階段解析,那時基類也會先於Y進行了解析,所以this-->g()調用了基類的g()。同樣,我們可以看看普通類的情況:

void g() { cout<<"gobal::g()"< class X {
public:
	typedef int E;
	void g() { cout<<"X::g()"< class Y : public X {
public:
	E f() { g(); this->g(); }
};

int main(){

	Y y;
	cout<結果會發現,兩次都調用了基類X的g(),這個例子告訴我們,在類模板中,如果需要使用成員函數,需要通過this指針來指定,而不能像在普通類中那樣省略到this指針,事實上,如果不用this指針來指定,而又沒有全局函數g(),編譯時會出現如下錯誤:
error:there are no arguments to 'g' that depend on a template parameter, so a declaration of 'g' must be available.





  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved