【问题标题】:accessing protected members of superclass in C++ with templates [duplicate]使用模板访问 C++ 中超类的受保护成员 [重复]
【发布时间】:2011-04-29 22:40:41
【问题描述】:

为什么 C++ 编译器不能识别 g()bSuperclass 的继承成员,如下代码所示:

template<typename T> struct Superclass {
 protected:
  int b;
  void g() {}
};

template<typename T> struct Subclass : public Superclass<T> {
  void f() {
    g(); // compiler error: uncategorized
    b = 3; // compiler error: unrecognized
  }
};

如果我简化 Subclass 并仅从 Subclass&lt;int&gt; 继承,那么它会编译。当将 g() 完全限定为 Superclass&lt;T&gt;::g()Superclass&lt;T&gt;::b 时,它也会编译。我正在使用 LLVM GCC 4.2。

注意:如果我在超类中将 g()b 设为 public,它仍然会失败并出现同样的错误。

【问题讨论】:

  • 发生这种情况是因为两阶段名称查找(并非所有编译器都默认使用)。这个问题有4个解决方案:1)使用前缀Superclass&lt;T&gt;::bSuperclass&lt;T&gt;::g()2)使用前缀this-&gt;athis-&gt;g()3) 添加语句using Superclass&lt;T&gt;::ausing Superclass&lt;T&gt;::g4) 使用启用许可模式的全局编译器开关。这些解决方案的优缺点在stackoverflow.com/questions/50321788/… 中进行了描述

标签: c++ templates inheritance


【解决方案1】:

这可以通过使用using 将名称拉入当前范围来修改:

template<typename T> struct Subclass : public Superclass<T> {
  using Superclass<T>::b;
  using Superclass<T>::g;

  void f() {
    g();
    b = 3;
  }
};

或者通过this指针访问限定名称:

template<typename T> struct Subclass : public Superclass<T> {
  void f() {
    this->g();
    this->b = 3;
  }
};

或者,正如您已经注意到的,通过限定全名。

之所以有必要这样做是因为 C++ 没有考虑超类模板来进行名称解析(因为它们是从属名称并且不考虑从属名称)。它在您使用 Superclass&lt;int&gt; 时有效,因为它不是模板(它是模板的实例化),因此它的嵌套名称不是依赖 名称。

【讨论】:

  • 微软的编译器不遵守这个规则。我很生气
  • @Armen:只有这一条规则?哇,它真的已经变得更好了。 :-D
  • this 指针解决方案适用于我在 Mac 10.7 上使用 stock g++。
  • 请注意,如果模板参数过多,您也可以使用Subclass::Superclass:: 进行限定。
  • 我有点喜欢微软不遵守这条规则。我真的希望有一个选项可以将模板的所有符号检查延迟到实例化。它将显着提高模板的表现力并减少许多语法噪音。
【解决方案2】:

康拉德的回答并没有问或回答所有这一切中的最后一个“为什么”。不仅仅是 C++ 委员会武断地说“嘿,放弃从属名称,反正没人喜欢它们”。相反,编译器甚至在它们被实例化之前就对模板进行了一些检查,并且在它知道 T 之前它无法理解 g() 或 b,因为它不能 - 通常 - 在可能的特化之间进行选择基类(例如SuperClass&lt;X&gt; 可能有int bSuperClass&lt;Y&gt;void b()SuperClass&lt;Z&gt; 根本没有b)。更明确的形式只是说“相信我 - 这必须在实例化时来自基类(否则会出现编译器错误)”。

【讨论】:

  • 有点道理,但它绝对是模板中比较晦涩的“功能”之一。
  • @ChrisWue:那场比赛竞争激烈! ;-)
  • GCC 在过去(1990 年代)能够处理这个问题,但后来随着 C++ 的发展,它发生了变化。我认为它的处理方式在某些情况下会导致问题,这就是它被改变的原因。
猜你喜欢
  • 2012-05-26
  • 2013-09-17
  • 2016-04-06
  • 2012-12-01
  • 2011-03-22
  • 2012-11-20
  • 2010-12-22
  • 1970-01-01
相关资源
最近更新 更多