首页 > 解决方案 > 为什么类不能继承其父类的成员类型?

问题描述

template<typename T>
struct A
{
    using U = int;
};

struct B : A<int>
{
    void f(U) // ok
    {}
};

template<typename T>
struct C : A<int>
{
    void f(U) // ok
    {}
};

template<typename T>
struct D : A<T>
{
    void f(U) // fatal error: unknown type name 'U'
    {}
};

int main()
{
    B      b; // ok
    C<int> c; // ok
    D<int> d; // error
}

为什么类不能继承其父类的成员类型?

标签: c++ooptemplatesinheritancestandards

解决方案


该成员U像任何其他成员一样被继承,无论模板化了哪些类,但根据 C++17 [temp.dep]/3 的非限定名称查找找不到它:

在类或类模板的定义中,在非限定名称查找期间,无论是在类模板或成员的定义点,还是在类模板的实例化期间,都不会检查依赖基类 (17.6.2.1) 的范围成员。

这里,A<T>是一个依赖基类,因为它依赖于T类模板的模板参数D

要强制编译器U在基类中查找,您必须使用限定名称查找。你可以这样做:

void f(typename A<T>::U);

如果基类的模板参数很复杂,另一种表达方式是:

void f(typename D::A::U);

如果你要多次写出来,那么你也可以D为了方便重新声明类型:

using U = typename A<T>::U;
void f(U);

注意:在上述上下文中,typename在 C++20 中将变为可选。


推荐阅读