访问嵌套类(它们的行为像朋友,但不是)

Access of nested classes (which behave like friends, but aren't)

本文关键字:朋友 嵌套 访问      更新时间:2023-10-16

没有长时间的延迟,下面是我不知道它为什么会这样做的代码:

#include <iostream>
class A {
private:
  void print() { std::cout << "A.print() called" << std::endl; };
public:
  template<typename Foo>
  class B; //NOTE: no friend!
public:
  A();
  B<double>*  bd;
  B<int>*     bi;
}; 
template<typename Foo>
class A::B{
  A* callback;
public:
  B(A* a):callback(a){};
  void print() { callback->print(); }; // Why is this working ???
};
A::A():bd(new B<double>(this)),bi(new B<int>(this)){}
int main(int argc, char **argv)
{
  A a;
//   a.print(); // error: ‘void A::print()’ is private
  a.bd->print();
  a.bi->print();
  A::B<char> c(&a);
  c.print();
  A::B<double> d = *a.bd;
  d.print();
  return 0;
}

好吧,它创建了这个输出:

A.print() called
A.print() called
A.print() called
A.print() called

但为什么

背景

当我遇到一个与friend s有关的问题时,我开始了我的兔子洞之旅。所以我阅读了朋友声明而不是转发声明(以及这里和这里提到的答案)。因此,在尝试设置一个简单的示例(您可以看到上面的结果)时,我发现实际上我似乎根本不需要friend

问题

因此,这里有一个底线问题:为什么A::B的实例可以访问A的私有函数A::print()(尽管我确实意识到我可能误解了我的孩子是什么——孩子,而不是基础派生

因为嵌套类是封闭类的成员

标准11.7.1美元

"嵌套类是一个成员,因此具有与任何其他成员相同的访问权限。封闭类的成员对嵌套类的成员没有特殊访问权限;应遵守通常的访问规则"

通常的访问规则规定:

"一个类的成员也可以访问该类可以访问的所有名称…"

标准中给出了具体的例子:

class E {
    int x;
    class B { };
    class I {
        B b; // OK: E::I can access E::B
        int y;
        void f(E* p, int i) {
            p->x = i; // OK: E::I can access E::x
        }
    };
}

嵌套类(或内部类)可以访问其嵌套的类的私有部分。从某种意义上说,它已经是那个班的朋友了。这类似于任何A对象访问任何其他A对象的私有对象的方式。

friend用于在要访问其私有的类之外定义的类。这里有一个简单的例子:

struct B;
class A
{
  int x;
  friend struct B;
};
struct B
{
  void someFunc() {
    A a;
    a.x = 5;
  }
};
int main(int argc, const char* argv[])
{
  B b;
  b.someFunc();
  return 0;
}

如果不使B成为A的朋友,它将无法访问A的成员x