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指针后边的内容都是成员变量,对于成员变量有两种情况,第一种就是在当前类中定义的变量,会在第一阶段的时候进行检查。当第一阶段无法查找到该成员的时候,就会考虑是不是父类的成员,如果父类是一个模板类,那么需要在第二阶段进行编译,因此编译器会记录下这个成员,等到第二阶段去父类中对该成员进行查找。

总结:

对于上述的问题,本质是看子类能不能在实例化之前找到其父类。如果父类是模板类就需要在实例化之后才能找到。

猜你喜欢

转载自blog.csdn.net/yzcwansui/article/details/86503802