Effective C++ 条款43 学习处理模板化基类内的名称

1. 在继承模板基类时,C++拒绝在模板化基类(templatized base classes)内寻找继承而来的名称,例如,对于以下模板基类:

template<typename T>
class Base{
public:
    void fun(){
        ...
    }
    ...
private:
    ...
}
View Code

以下代码通不过编译:

template<typename T>
class Derived:public Base<T>{
public:
    void useFun(){
        fun();  //通不过编译,因为编译器拒绝在Base类模板中查找fun
    }
    ...
private:
    ...
}
View Code

因为基类模板(base classe templates)有可能被特化,而那个特化版本可能不提供和一般性template相同的接口,因而C++拒绝在模板化基类中查找继承而来的名称.

2. 解决方法有三:

    1). 在base class函数调用动作之前加上this->,即将对fun的调用改为如下:

this->fun();

    2). 使用using 声明式,使编译器在模板作用域中查找改名字,即在Derived中加入:

using Base<T>::fun;

这里using声明式的作用和条款33不同,它解决的并不是基类名字被派生类掩盖的问题,而是编译器不进入base class作用域内查找的问题

    3). 明确指出被调用的函数位于base class内,即将对fun的调用改为如下:

Base<T>::fun();

    这种方式的缺点在于,如果被调用的函数是虚函数,上述的"明确资格修饰"(explict qualification)会关闭"virtual绑定行为".

3. 从名称可视点的角度出发,2中的每一个解法所做事情都相同:对编译器承诺"base classes template的任何特化版本都将支持其一般化版本所提供的接口".这个承诺是编译器在解析像Derived这样的派生类模板(derived class template)所需要的.但如果这个承诺未被实现即特化的Base不支持派生类模板Derived所要求的接口,最终还是不能通过编译.C++的策略是较早诊断,因此它假设它对那些base classes的内容毫无所悉的缘故.

原文地址:https://www.cnblogs.com/reasno/p/4801220.html