【问题标题】:Accessing inherited objects from class template从类模板访问继承的对象
【发布时间】:2014-07-01 00:32:56
【问题描述】:

我一直在学习 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 的实例。事实上,如果我直接从A 而不是B&lt;T&gt; 派生C,或者从C 中删除模板,它编译得很好。

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

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

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

感谢您的帮助!

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

【问题讨论】:

标签: c++ templates inheritance g++


【解决方案1】:

首先,您的代码使用 clang 编译(参见 here),而不是使用 gcc 编译。我也让它用 VS2013 编译。


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

标准第 14.6.2 节:

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

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

编译器不会在依赖的基类(如 B)中查找 查找不依赖的名称(如 vec)。


解决方案

1.使用this-&gt;vec(在模板中总是隐式依赖

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

2.使用using B&lt;T&gt;::vec

3.直接使用B&lt;T&gt;

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

注意事项:

  • 我不知道为什么 gcc 拒绝 using A::vec;,在我看来像是一个编译器错误(请注意 using B&lt;T&gt;::A::vec; 有效)。
  • 模板名称查找的标准参考:§ 14.6.3 和 § 14.6.4

【讨论】:

  • 感谢您的回答!我快速阅读了有关非依赖名称和依赖基类的问题(这就是我学习“使用 A::vec”语法的地方)。但是,我不知道你可以堆叠像 B::A::vec 这样的范围解析运算符——这很好知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-26
  • 2018-05-23
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多