首页 > 技术文章 > C++ 之处理模板化基类的成员名称

zhiyiYo 2022-06-26 16:18 原文

问题描述

假设有下面这么一段简单的代码,其中定义了两个类模板,一个基类 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> {
    
};

要想正确访问模板化基类中的成员,有以下三种方法:

  1. 使用 this 指针,比如 this->name_

  2. 使用 using 声明,如下述代码所示:

    template <typename T>
    class Dog : public Animal<T> {
    public:
        using Animal<T>::name_;
        string getName()
        {
            return name_;
        }
    };
    
  3. 使用 Animal<T>::name_ 显式指出成员在基类中,但是这种方法有个缺点,就是访问不了子类重写后的虚函数。

有一点需要指出的是,如果子类重写了模板化父类的虚函数,由于能在子类作用域中找到虚函数的名字,所以不需要 this 指针等方法就能调用该函数,以上~~

推荐阅读