从类模板访问继承的对象

p_a*_*a_c 5 c++ inheritance templates g++

我一直在学习C++模板,我遇到了一些奇怪的行为.考虑这个类结构(从我的原始代码中删除):

class A {
public:
    std::vector <int> vec;
};

template <typename T> class B : public A {  };

template <typename T> class C : public B<T> {
public:
    using A::vec;
    int test() {
        return vec[1];      // OK
    }

    int test2() {
        return vec.size();  // error: 'class A' has no member named 'size'
    }
};
Run Code Online (Sandbox Code Playgroud)

编译时,我收到错误test2,说class A没有成员size.但vec应该是一个vector对象,而不是一个实例A.事实上,如果我得到C直接A而不是B<T>,或删除的模板C,它编译罚款.

此外,如果我添加以下方法C:

int test3() {
    void ***v = vec;        // error: cannot convert from
                            // 'std::vector<int,...>'  to 'void***' 
}
Run Code Online (Sandbox Code Playgroud)

编译器说它无法从a转换vector<int>为void***,所以它似乎知道正确的类型vec.我在这里犯了错误,或者这可能是我的编译器中的错误?我正在使用Apple版的g ++ 4.2.1.编辑:似乎也出现在g ++的更高版本中.

谢谢你的帮助!

第二个编辑:我的编译器是高兴,如果我使用this->vec.size()的test2,而不是依靠的using A::vec声明.

qua*_*dev 2

首先,您的代码使用 clang 进行编译(请参阅此处),并且不使用gcc进行编译。我还用VS2013编译了它。

\n\n
\n\n

您最初的问题与编译器如何在模板中查找名称有关。

\n\n

标准 \xc2\xa7 14.6.2 :

\n\n
\n

模板定义中使用的非依赖名称是使用通常的名称查找找到的,并在使用它们时绑定。

\n
\n\n

C++ FAQ也有一个很好的条目:

\n\n
\n

当查找非依赖名称(如 vec)时,编译器不会查找依赖基类(如 B)。

\n
\n\n
\n\n

解决方案:

\n\n

1.使用this->vec(这始终隐式依赖于模板)

\n\n
int test2() {\n    return this->vec.size();  \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

2.使用using B<T>::vec

\n\n

3.直接使用B<T>:

\n\n
int test2() {\n    return B<T>::vec.size();  \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

笔记:

\n\n
    \n
  • 我不确定为什么 gcc 拒绝using A::vec;,对我来说看起来像是一个编译器错误(并注意它using B<T>::A::vec;有效)。
  • \n
  • 模板名称查找的标准参考:\xc2\xa7 14.6.3 和 \xc2\xa7 14.6.4
  • \n
\n