C++繼承模板類,需要使用this指針或者Base::調用成員變量

在C++中如果父類是模板類,直接調用父類成員的話,會報錯找不到該變量,其根本原因是因爲模板的二次編譯機制導致的。

其父類的聲明

template <typename T>
class SeqList:public List<T>{
protected:
	T* m_array;//順序存儲空間位置
	unsigned int length;//當前線性表長度
public:
	bool Insert(int i, const T& e);
	bool Remove(int i);
	bool Set(int i, const T& e);
	bool Get(int i, T& e)const;
	unsigned int Length()const;
	void Clear();

	//數組訪問方式
	T& operator [](int i);
	T  operator [](int i)const;

	//設置順序存儲空間容量
	virtual unsigned int Capacity()const = 0;
};

將子類寫成如下形式:

template<typename T, int N> //N爲數組大小
class StaticList: public SeqList<T>{
protected:
	T space[N];
public:
	StaticList(){
	//找不到父類的兩個變量
		m_array = space;
		length = 0;
	}

	unsigned int Capacity() const{
		return N;
	}
};

發現編譯器報錯說找不到父類中的兩個變量m_array,和length。
經過查詢發現,模板要編譯兩次。

模板定義階段(第一階段):

只對模板中和模板參數無關的名字進行查找(無視那些有模板參數的部分)。父類是模板類,在第一次編譯的時候會被無視掉。
for instance:
對於上邊的例子:
StaticList繼承自SeqList,在第一次編譯的時候編譯器會忽略掉SeqList,假裝沒有看到它,因此SeqList中的成員m_array和length就順理成章地被忽略了。在StaticList中沒有再次定義m_array和length,因此編譯器在第一次編譯的時候無法找到m_array和length直接報錯了。

模板實例化階段(第二階段)

在第二階段編譯器主要處理帶模板參數的部分,所有和模板相關的操作都在該階段完成。
給出一個例子,也就是上邊問題的解決方法。

子類:

template<typename T, int N> //N爲數組大小
class StaticList: public SeqList<T>{
protected:
	T space[N];
public:
	StaticList(){
		//父類是模板可以用Base::來調用父類成員
		SeqList<T>::m_array = space;
		//父類是模板可以用this來調用父類成員
		this->length = 0;
	}
	unsigned int Capacity() const{
		return N;
	}
};

在這個子類中,在每個成員變量之前加入了Base::或者this指針,通過Base::或者this指針,將成員變量拖到第二階段進行編譯。this指針後邊的內容都是成員變量,對於成員變量有兩種情況,第一種就是在當前類中定義的變量,會在第一階段的時候進行檢查。當第一階段無法查找到該成員的時候,就會考慮是不是父類的成員,如果父類是一個模板類,那麼需要在第二階段進行編譯,因此編譯器會記錄下這個成員,等到第二階段去父類中對該成員進行查找。

總結:

對於上述的問題,本質是看子類能不能在實例化之前找到其父類。如果父類是模板類就需要在實例化之後才能找到。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章