2

$10.2/4- "[ 注: たとえば、精巧な型指定子 (3.4.4) または基本指定子 (第 10 節) で名前を検索すると、すべての非型宣言が無視され、入れ子になった型指定子で名前が検索されます。 name-specifier (3.4.3) は、関数、変数、および列挙子の宣言を無視します。"

名前の検索について説明しているときに、このセクションでこのステートメントが非常に紛らわしいことがわかりました。

void S(){}

struct S{
   S(){cout << 1;}
   void f(){}
   static const int x = 0;
}; 

int main(){ 
   struct S *p = new struct ::S;  // here ::S refers to type
   p->::S::f();

   S::x;  // base specifier, ignores the function declaration 'S'

   ::S(); // nested name specifier, ignores the struct declaration 'S'.
   delete p;
} 

私の質問:

  1. ルールに対する私の理解は正しいですか?

  2. 最後の行では、グローバル名前空間の関数を意味するのに対し、行では、::S新しい処理を自動的に struct を意味するのはなぜですか。S::SS

  3. これはドキュメントのあいまいさを示しているのでしょうか、それとも C++ 標準ドキュメントから離れる日がまた来るのでしょうか?

4

2 に答える 2

2

Q1: そう思います。

Q2: C との互換性。Cstructで a を宣言すると、タグ名はそのままタグ名になります。スタンドアロンで使用するには、typedef. C++ では、typedef は必要ないため、ライブが簡単になります。しかし、関数名でタグ名を「オーバーロード」した既存の C ヘッダーをインポートできるようにする必要があるため、C++ のルールは複雑になっています。その標準的な例は、引数としてstat()a を使用する Unix 関数です。struct stat*

Q3: 通常、標準的な読み方は非常に難しいです... あなたが読んでいるものを修正する場所は他にないことを知っておく必要があります。その方法を知っている人が言語弁護士であることは不思議ではありません...

于 2010-11-04T06:43:08.247 に答える
0

あなたは2番目のコメントについて間違っています。ではS::xSはネストされた名前指定子内の名前です。標準が「base-specifier」で参照するものは次のとおりです

namespace B { struct X { }; void X() }
struct A : B::X { }; // B::X is a base-specifier

これについても正しくありません:

::S(); // ネストされた名前指定子は、構造体宣言 'S' を無視します。

そのコードは::S、ネストされた名前指定子 (ネストされた名前指定子ではありません!) になるためではなく、関数とクラス/列挙の両方が宣言されている場合、関数名がクラスまたは列挙名を非表示にするため、関数を呼び出します同じ範囲。

FWIW、次のコードはメインの2行目でも同様に有効です

p->S::f();

重要なのは、それがSa の::前にあるということです。これにより、ルックアップで関数が無視されます。あなたが:: Sに置いたことは、あなたの場合には効果がありません。

于 2011-08-15T15:17:53.720 に答える