在C++中,继承类模板时,调用基类的成员时,需要通过this
指针或者基类名来调用。否则会出现编译错误。
问题代码1
template <typename T>
class base {
protected:
int x;
};
template <typename T>
class derived : public base<T> {
public:
int f() { return x; } // error: use of undeclared identifier 'x'
};
int main() {
derived<int> d;
d.f();
return 0;
}
原因分析2.3
两阶段编译
- 第一阶段:当编译器看到模板时,它也会立即执行某些检查,但所有和模板参数相关的检查都会被推迟到实例化模板的时候。此时父类是模板类,在这一阶段会被忽略。
- 第二阶段:在实例化模板的时候,才会对模板参数进行查找。
结合本例:
- 父类
base
是模板类,所以在第一阶段编译时,编译器会忽略父类的成员。 - 但是第一阶段编译时,编译器无法找到
x
,所以会报错。
解决方法
通过this
指针调用基类成员。将其推迟到第二阶段编译时,这时候编译器已经知道base
的成员。
具体的代码就是将return x;
改为return this->x;
。
template <typename T>
class base {
protected:
int x;
};
template <typename T>
class derived : public base<T> {
public:
int f() { return this->x; } // error: use of undeclared identifier 'x'
};
int main() {
derived<int> d;
d.f();
return 0;
}
以一个伪代码来分析代码会在哪个阶段报错4
template <class T>
T add(T a, T b)
{
undefine(); //未定义,与模板参数无关,第一阶段报错
undefine(a, b); //未定义,与模板参数有关,二阶段报错
static_assert(sizeof(int) > 100, "Error!"); //与模板参数无关,一阶段报错
static_assert(sizeof(T) > 100, "Error!");//与模板参数有关,二阶段报错
return a + b;
}