C++ 之处理模板化基类的成员名称
问题描述
假设有下面这么一段简单的代码,其中定义了两个类模板,一个基类 Animal
,一个派生类 Dog
:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class Animal {
protected:
string name_ = "animal";
};
template <typename T>
class Dog : public Animal<T> {
public:
string getName()
{
return name_;
}
};
int main(int argc, char const* argv[])
{
Dog<int> dog;
cout << dog.getName();
return 0;
}
在狗狗类中有个 getName()
方法,返回基类部分的成员 name_
,感觉看上去没什么问题,但是编译的时候却会报错:
问题解决
出现这个问题的原因在于,在 Animal<T>
被实例化之前,编译器无法得知里面是否有 name_
这个数据成员。比如我们自己全特化一个空的 Animal
,这里面就啥也没有:
template <>
class Animal<int> {
};
要想正确访问模板化基类中的成员,有以下三种方法:
-
使用
this
指针,比如this->name_
; -
使用
using
声明,如下述代码所示:template <typename T> class Dog : public Animal<T> { public: using Animal<T>::name_; string getName() { return name_; } };
-
使用
Animal<T>::name_
显式指出成员在基类中,但是这种方法有个缺点,就是访问不了子类重写后的虚函数。
有一点需要指出的是,如果子类重写了模板化父类的虚函数,由于能在子类作用域中找到虚函数的名字,所以不需要 this
指针等方法就能调用该函数,以上~~