1. ホーム
  2. c++

[解決済み] なぜC++は継承された友情を許さないのですか?

2023-01-19 12:56:49

質問

なぜ C++ では友情は少なくともオプションとして継承されないのでしょうか? 私は、transitivity と reflexivity が明白な理由で禁止されていることは理解していますが (これは単純な FAQ の引用回答を回避するために言っているだけです)、以下のようなものがないのは残念です。 virtual friend class Foo; のようなものがないことが私を困惑させています。 この決定の背後にある歴史的背景をご存知の方はいらっしゃいますか? 友情は本当に限られたハックであり、その後、いくつかの不明瞭な立派な用途に道を見つけたのでしょうか?

明確化のために編集します。 次のシナリオについて話しています。 ではなく ここで、Aの子はBのどちらか、またはBとその子の両方に公開されます。 また、フレンド関数のオーバーライドへのアクセスをオプションで許可することなども想像できます。

class A {
  int x;
  friend class B;
};

class B {
  // OK as per friend declaration above.
  void foo(A& a, int n) { a.x = n; }
};

class D : public B { /* can't get in A w/o 'friend class D' declaration. */ };

回答受付中です。 として ロキ状態 のように、友好的な基底クラスで保護されたプロキシ関数を作ることによって、その効果を多かれ少なかれシミュレートすることができますので、厳密な が必要です。 はありません。 私は定型的なプロキシ(フレンドベースが事実上そうなる)の必要性が嫌いですが、ほとんどの場合誤用される可能性が高い言語メカニズムよりも望ましいと判断されたのでしょう。 そろそろStroupstrupの C++ の設計と進化

C++ の設計と進化 という本がありますが、この種の質問に対するより良い洞察を得るために、私はここで多くの人が勧めるのを見てきました...

どのように解決するのですか?

なぜなら、私は Foo と書くことができ、その友人である Bar (というように、信頼関係があります)。

から派生したクラスを書く人は信頼できるのでしょうか? Bar ?

そうではありません。だから、友情を受け継ぐべきでない。

クラスの内部表現を変更すると、その表現に依存しているすべてのものに変更が必要になります。したがって、クラスのすべてのメンバー、またクラスのすべてのフレンドは、修正を必要とします。

したがって、もし内部表現が Foo が変更された場合 Bar も変更されなければなりません (友情は BarFoo ). もし友情が継承されたなら、すべての Bar から派生したクラスもまた Foo に強く結合しているため、もし Foo の内部表現が変更された場合、修正が必要になります。しかし、私は派生型についての知識がありません (別の会社によって開発されているかもしれませんし、そうである必要もありません)。従って、私は Foo から派生したすべてのクラスを変更することはできません。 Bar ).

したがって、もし友情が継承されたのであれば、クラスを修正する能力に不注意にも制限を導入することになります。これは、基本的にパブリック API の概念を無にするものであり、望ましいことではありません。

注意: Bar にアクセスすることができます。 Foo にアクセスするには Bar にあるメソッドを Bar を保護します。そして、その子である Bar にアクセスすることができます。 Foo へのアクセスは、親クラスを経由して呼び出すことで可能です。

これでいいのでしょうか?

class A
{
    int x;
    friend class B;
};

class B
{
    protected:
       // Now children of B can access foo
       void foo(A& a, int n) { a.x = n; }
};

class D : public B
{
    public:
        foo(A& a, int n)
        {
            B::foo(a, n + 5);
        }
};