c++ - 私有(private)继承的 typedef 对嵌套类的可见性

标签 c++ inheritance typedef nested-class

在下面的示例中(对长度表示歉意)我试图隔离一些我在从另一个私有(private)继承的类中使用嵌套类时遇到的意外行为。我经常看到这样的陈述:与非嵌套类相比,嵌套类没有什么特别之处,但在这个例子中,可以看到嵌套类(至少根据 GCC 4.4)可以看到一个公共(public)类型定义由关闭类私有(private)继承的类。

我明白 typdef 与成员数据不同,但我发现这种行为令人惊讶,而且我想很多其他人也会这样。所以我的问题是双重的:

  1. 这是标准行为吗? (对原因的合理解释会很有帮助)
  2. 能否期望它适用于大多数现代编译器(即它的可移植性如何)?

#include <iostream>

class Base {
  typedef int priv_t;
  priv_t priv;
public:
  typedef int pub_t;
  pub_t pub;
  Base() : priv(0), pub(1) {}
};

class PubDerived : public Base {
public:
  // Not allowed since Base::priv is private
  // void foo() {std::cout << priv << "\n";}

  class Nested {
    // Not allowed since Nested has no access to PubDerived member data
    // void foo() {std::cout << pub << "\n";}

    // Not allowed since typedef Base::priv_t is private
    // void bar() {priv_t x=0; std::cout << x << "\n";}
  };

};

class PrivDerived : private Base {
public:
  // Allowed since Base::pub is public
  void foo() {std::cout << pub << "\n";}

  class Nested {
  public:
    // Works (gcc 4.4 - see below)
    void fred() {pub_t x=0; std::cout << x << "\n";}
  };
};

int main() {

  // Not allowed since typedef Base::priv_t private
  // std::cout << PubDerived::priv_t(0) << "\n";

  // Allowed since typedef Base::pub_t is inaccessible
  std::cout << PubDerived::pub_t(0) << "\n"; // Prints 0

  // Not allowed since typedef Base::pub_t is inaccessible
  //std::cout << PrivDerived::pub_t(0) << "\n";

  // Works (gcc 4.4)
  PrivDerived::Nested o;
  o.fred(); // Prints 0
  return 0;
}

最佳答案

前言:在下面的回答中,我提到了 C++98 和 C++03 之间的一些差异。然而,事实证明我所说的变化还没有进入标准,所以 C++03 在这方面与 C++98 并没有真正的不同(感谢 Johannes 指出这一点)。不知何故,我确定我在 C++03 中看到了它,但实际上它不存在。然而,这个问题确实存在(请参阅 Johannes 评论中的 DR 引用)并且一些编译器已经实现了他们可能认为是该问题的最合理解决方案。因此,下文中对 C++03 的引用是不正确的。请将对 C++03 的引用解释为对这种行为的一些假设但很可能是 future 规范的引用,一些编译器已经在尝试实现它。


请务必注意,C++98 和 C++03 标准之间嵌套类的访问权限发生了重大变化。

在 C++98 中,嵌套类对封闭类的成员没有特殊的访问权限。它基本上是完全独立的类,只是在封闭类的范围内声明。它只能访问封闭类的公共(public)成员。

在 C++03 中,嵌套类被授予访问封闭类成员的权限,作为封闭类的成员。更准确地说,嵌套类被授予与封闭类的静态成员函数相同的访问权限。 IE。现在嵌套类可以访问封闭类的任何成员,包括私有(private)成员。

因此,您可能会观察到不同编译器和同一编译器版本之间的差异,具体取决于它们何时实现了新规范。

当然,您必须记住嵌套类的对象不以任何方式绑定(bind)到封闭类的任何特定对象。就实际对象而言,这是两个独立的类。为了从嵌套类访问封闭类的非静态数据成员或方法,您必须具有封闭类的特定对象。换句话说,嵌套类的行为确实就像封闭类的静态成员函数:它没有针对封闭类的特定this 指针,所以它不能访问封闭类的非静态成员,除非你努力给它一个封闭类的特定对象来访问。没有它,嵌套类只能访问封闭类的类型定义名称、枚举和静态成员。

一个简单的例子说明了 C++98 和 C++03 之间的区别,如下所示

class E {
  enum Foo { A };
public:
  enum Bar { B };

  class I {
    Foo i; // OK in C++03, error in C++98
    Bar j; // OK in C++03, OK in C++98
  };
};

此更改正是允许您的 PrivDerived::Nested::fred 函数编译的原因。它不会在迂腐的 C++98 编译器中通过编译。

关于c++ - 私有(private)继承的 typedef 对嵌套类的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2421492/

相关文章:

c++ - 使用 OGDF 布置边缘?

c++ - 用C++标准库分析Clang线程安全

c++ - 从派生类中的模板化基类使用 typedef/using

部分模板实例化中的 C++ Typedef

c++ - 关于 C++ 中 rand() 函数的困惑

c++ - 在 C++ GPGPU 库中嵌入 cg 着色器

c++ - C++ 中的继承 : Error C2011

Java:我根本不理解这个泛型定义

Ruby 套接字继承

c - 使用 typedef 在 C 中实现抽象数据类型