1

長い間遅れることなく、ここで、なぜそれが何をするのか見当がつかないコードを示します。

#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

しかし、なぜ?

バックグラウンド

sに関係する問題に遭遇したとき、私は最初にうさぎの穴を下る旅を始めましたfriend。だから私は、前方宣言ではなく友人宣言を読みました(そして、言及された答えはここここにあります)。そのため、簡単な例 (上記の結果) を設定しようとしているときに、実際にはまったく必要ないように思われることがわかりましたfriend

質問

結論の質問は次のとおりです:のインスタンスがのプライベート関数にアクセスできるのはなぜですか? A::BAA::print()(ただし、自分の子供が何であるかを誤解している可能性があることは認識しています-ベース派生ではなく子供です)

4

2 に答える 2

4

ネストされたクラスは囲んでいるクラスのメンバーであるため

標準 $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
        }
    };
}
于 2013-02-07T19:09:21.647 に答える
2

ネストされたクラス (または内部クラス) は、ネストされているクラスのプライベートにアクセスできます。ある意味で、すでにそのクラスと友達になっています。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にアクセスできません。Ax

于 2013-02-07T19:06:55.077 に答える