简体   繁体   English

从类模板访问继承的对象

[英]Accessing inherited objects from class template

I've been learning C++ templating and I've run across some weird behavior. 我一直在学习C ++模板,我遇到了一些奇怪的行为。 Consider this class structure (stripped down from my original code): 考虑这个类结构(从我的原始代码中删除):

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'
    }
};

When compiling, I get an error in test2 , saying that class A has no member size . 编译时,我在test2得到一个错误,说class A没有成员size But vec should be a vector object, not an instance of A . 但是vec应该是一个vector对象,而不是A的实例。 Indeed, if I derive C directly from A instead of B<T> , or remove the template from C , it compiles fine. 实际上,如果我直接从A而不是B<T>派生C ,或者从C删除模板,那么它编译得很好。

Furthermore, if I add the following method to C : 此外,如果我将以下方法添加到C

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

the compiler says it can't convert from a vector<int> to void*** , so it seems to know the correct type for vec . 编译器说它无法从vector<int>转换为void*** ,因此它似乎知道vec的正确类型。 Am I making a mistake here, or is this possibly a bug in my compiler? 我在这里犯了错误,或者这可能是我的编译器中的错误? I'm using an Apple version of g++ 4.2.1. 我正在使用Apple版的g ++ 4.2.1。 Edit: also seems to occur in later versions of g++. 编辑:似乎也出现在g ++的更高版本中。

Thanks for your help! 谢谢你的帮助!

Second edit : my compiler is happy if I use this->vec.size() in test2 instead of relying on the using A::vec declaration. 第二次编辑 :如果我在test2使用this->vec.size()而不是依赖于using A::vec声明,我的编译器很高兴。

First, your code compiles with clang (see it here ), and doesn't compile with gcc . 首先,你的代码用clang编译( 在这里看到),不用gcc编译。 I also got it to compile with VS2013. 我也用VS2013编译它。


Your original issue is related to how the compiler lookup names in templates. 您的原始问题与编译器在模板中查找名称的方式有关。

The Standard § 14.6.2 : 标准§14.6.2:

Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used. 模板定义中使用的非依赖名称可以使用通常的名称查找找到,并在使用它们时绑定。

Also the C++ FAQ has a good entry about it : 此外, C ++ FAQ有一个很好的条目:

The compiler does not look in dependent base classes (like B) when looking up nondependent names (like vec). 查找非依赖名称(如vec)时,编译器不会查找依赖的基类(如B)。


Solution : 方案

1. Use this->vec (this is always implicitly dependent in a template) 1.使用this->vec (这总是隐含地依赖于模板)

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

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

3. Use B<T> directly : 3.直接使用B<T>

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

Notes: 笔记:

  • I'm not sure why gcc refuses using A::vec; 我不确定为什么gcc拒绝using A::vec; , looks like a compiler bug to me (and note that using B<T>::A::vec; works). ,看起来像一个编译器错误(并注意using B<T>::A::vec;工作)。
  • Standard reference for template names lookup : § 14.6.3 and § 14.6.4 模板名称查找的标准参考:§14.6.3和§14.6.4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM