0

「C++プログラミング言語」のセクション11.5.1で、BjarneStroustrupは次のように書いています。

メンバー宣言と同様に、フレンド宣言は名前を囲んでいるスコープに導入しません。

例えば:

class Matrix
{
    friend class Xform;
    friend Matrix invert (const Matrix &);
//..
 };
Xform x; // error: no Xform in scope
Matrix (*p) (const Matrix &) = &invert; // error: no invert() in scope

大規模なプログラムや大規模なクラスの場合、クラスがそれを囲むスコープに「静かに」名前を追加しないのは良いことです。多くの異なるコンテキストでインスタンス化できるテンプレートクラス(第13章)の場合、これは非常に重要です。

ただし、次のセクションでは、クラスが以前に定義されているか、フレンドを宣言しているクラスをすぐに囲む非クラススコープで定義されている必要があることを説明します。

私の質問は、クラスが以前に定義されているか、クラスをフレンドと宣言しているクラスをすぐに囲む非クラススコープで定義されている必要があるため、最初の例でXformは、おそらくクラスがスコープ外になることはありません。Matrixクラスの定義の前に定義されています。さらに、フレンドクラスを事前に定義するか、付与者のクラスの直後に定義する必要があるという制限があるため、フレンドクラスがスコープに含まれないという状況は考えられません。

第二に、このセクションでのBjarneの私の解釈は正しいですか?

  • フレンドクラスの場合のみ、フレンドクラスは、囲んでいるスコープで事前に定義されているか、非クラススコープの直後に定義されている必要があります。
  • 関数の場合、囲んでいるスコープで事前に宣言されている必要があります。または、タイプ=='フレンドシップ付与者の'クラスの引数を持つことによっても見つけることができますか?
4

4 に答える 4

2

サンプルコードが機能するはずだった場合、Xform以前に定義されている必要があるのは正しいです。しかし、それはうまくいくはずがありませんでした。これは悪いコードの例でした— フレンド宣言で新しい名前をプログラムに導入し、それらの名前を使用して変数を宣言し、ポインターを初期化しようとするコードです。Matrix

以上がスタンドアロンの例です。と の定義など、特定のコードの前後に追加のコードを想像することになっている単なる抜粋ではありませんでしXforminvert

あなたの最初の言い換えは完全に正しくありません。フレンド クラスの定義は、フレンドシップを付与したクラスの直後である必要はありません。すぐ外側の scopeで定義する必要があります。本質的に、それはそれが友達であるクラスと同じスコープで定義されるべきです。あなたが引用した後の例はそれを示しています:

class AE { /* ... */ }; // not a friend of Y

namespace N {
  class X { /* ... */ }; // Y's friend

  class Y {
    friend class X;
    friend class Z;
    friend class AE;
  };

  class Z { /* ... */ }; // Y's friend
}

それはその友達だと言いますが、名前空間はのすぐ外側のスコープであり、そこで宣言されていないため、以前に宣言されたクラスを参照しYていません。代わりに、friend 宣言は、プログラム内の別の場所にある名前空間で定義される他のクラスを参照する必要があります。(ただし、どこにも定義する必要はまったくありません。クラスは、存在しないものと友達であると言うことができ、プログラムは気にしません。ただし、プログラマーは気にします。時間を無駄にするからです。ソースコードで適切なクラスを見つけようとしています。)AEAENYAE AENAE

2番目の言い換えも間違っています。関数は、外側のスコープで事前に宣言されている必要はありません。最終的に宣言する必要があります。セクション 11.5 の最初の例を考えてみましょう。演算子が宣言または定義される前に、 はとクラスoperator*の両方のフレンドとしてリストされています。VectorMatrix

さらに、フレンド関数が見つかるために、クラスの型と等しい引数を持っている必要はありません。Stroustrup は、この関数は「その引数を介して見つけることができる」と述べ、それが何を意味するかについてセクション 8.2.6 を参照してください。それがname lookupのセクションです。

于 2009-10-28T01:59:06.837 に答える
1

Matrix がスコープ内にあり、XForm がスコープ内にない場合の例ですが、Matrix のフレンドである XForm クラスが定義されています。

1.h
------------------------
namespace Foo
{
 class Matrix
 {
  friend class XForm;
 };
}

1.c
------------------------
#include 1.h
// XForm not in scope
// implement Matrix

2.h
------------------------
namespace Foo
{
 class XForm
 {
 };
}

main.c

#include 1.h
#include 2.h
int main()
{
 // both XForm & Matrix in scope here
}

これは正しいです?

于 2009-10-29T00:15:07.120 に答える
0

私があなたの質問を理解しているかどうかはわかりませんが、Bjarneは、クラスを使用する場合は、Xform外部でクラスを定義する必要があると考えていたと思いますMatrix(ヘッダーファイルに入れたヘルパークラスを想像してみてください)。 #includeファイルを#include含むすべてのファイルで)。あなたがそれについて言及しないのであれば、あなたはそれを定義する必要はありません:).cppMatrix

関数の場合も同様です。ただし、それは友人宣言(=クラス内)で定義することもでき、Matrixあなたが言うように、「タイプ=='友情付与者の'クラスの引数を持つことによって見つけることができる」(または持っている)という違いがありますそのネストされたクラスである引数タイプ)、Koenigルックアップによる。

于 2009-10-28T01:15:34.183 に答える
0

フレンド関数の考え方は、通常は他のクラスが内部にアクセスできないようにプライベート クラスがある場合です。ブラック ボックスを作成していますが、そのルールの例外である外部の関数に具体的に名前を付けたいと考えています。スコープとはあまり関係がないか、どちらかといえば特別な種類のスコープを定義していると考えるべきだと思います。

友人として定義されたものは、別の場所で定義する必要があります。そうでなければ、それは友人ではありません - それは何もありません - それは存在しません。

それが質問でしたか?

于 2009-10-28T01:26:18.063 に答える