从类模板访问继承的对象

时间:2014-07-01 00:32:57

标签: c++ templates inheritance 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'
    }
};

编译时,我在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***' 
}

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

感谢您的帮助!

第二次修改:如果我在this->vec.size()中使用test2而不是依赖using A::vec声明,我的编译器会很高兴。

1 个答案:

答案 0 :(得分:2)

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


您的原始问题与编译器在模板中查找名称的方式有关。

标准§14.6.2:

  

模板定义中使用的非依赖名称可以使用   通常的名称查找和绑定在他们使用的点。

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

  

编译器在查找依赖基类(如B)时   查找非依赖名称(如vec)。


解决方案

1。使用this->vec(模板中始终隐式依赖

int test2() {
    return this->vec.size();  
}

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

3。直接使用B<T>

int test2() {
    return B<T>::vec.size();  
}

备注:

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