5

好き :

using ::size_t; using ::fpos_t; using ::FILE;

実際、これはこの質問の下のコメントに触発された質問です。

ヘッダーファイルをインクルードするために.hが不要なのはいつですか?

4

5 に答える 5

8

これは、宣言を使用して呼び出されます。usingキーワードを使用する方法は実際には2つあります。クラス定義内で使用されるusing宣言の3番目の特別な形式がありますが、ここでは一般的なusing宣言に焦点を当てます。(下記参照)。

  • 宣言を使用する
  • ディレクティブを使用する

これらには2つの非常に異なる効果があります。using宣言は、名前が別の宣言または一連の宣言(オーバーロードされた関数のセットに名前を付ける場合)のエイリアスであると宣言します。名前は現在のスコープで宣言されています。つまり、ブロック内でも使用できます

int main() {
  using std::swap;
  // ...
}

これは、ローカルで頻繁に名前を使用し、すべての用途で名前のプレフィックスを付けたくない場合に非常に役立ちます。また、引数に依存するルックアップイディオムを使用してスワップを実装する場合にも役立ちます。

usingディレクティブは名前空間に名前を付け、名前を宣言しません。代わりに、名前ルックアップを変更して、実際には宣言されていない名前を見つけます。非修飾名ルックアップの場合、usingディレクティブとターゲット名前空間の両方を囲む名前空間で宣言された名前を検索します。ターゲット名前空間で宣言されているすべての名前が見つかります。

int cout;
int main() {
  using namespace std;
  // cout << 1; ambiguous!
}

ここでcoutは、グローバル名前空間で2回宣言されていると見なされ、あいまいさが生じます(との両方を::囲みます)。修飾されたnamelookupでは、ディレクティブを使用して指定されたすべての名前空間を使用して、名前空間の推移閉包を構築します。mainstd

using namespace foo;

int main() {
  ::c++; 
}

cグローバル名前空間だけでなく、名前空間fooや、などのfooディレクティブを使用している名前空間でも検索されます。ただし、グローバル名前空間に直接宣言(using宣言を含む)が含まれる場合、その宣言は、ディレクティブを使用して間接的に検出された宣言を非表示にします。

using namespace foo;
int c;

int main() {
  ::c++; // not ambiguous!
}

宣言の使用は、クラス定義内を含む多くの場所に現れる可能性があります。その意味は、他の場所での意味と似ていますが、重要な制限があります。名前を1つ以上の宣言のエイリアスとして宣言しますが、宣言は基本クラスのメンバーである必要があります。これは、派生クラスで名前を表示する場合に非常に便利です。派生クラスでは、そこで宣言されている同じ名前で名前が非表示になります。

struct base {
  void f();
};

struct derived : base {
  using base::f; // name "f" declared in derived
  void f(int); // overloads the using declaration
};

これで、を呼び出すことができますd.f()。using宣言がなかった場合、名前ルックアップはfinの宣言を1つだけ見つけてルックderivedアップを停止し、基本クラスのスコープを調べません。

derived d;
d.f(); // invalid without the using declaration
d.f(0); // valid with or without the using declaration

// explicitly starting lookup in base: valid with or without the using declaration
d.base::f();

また、基本クラスのメンバーのアクセシビリティを変更することもできますが、慎重に使用する必要があります:)

実際には、仮想メンバー関数を再表示するのに役立つことがわかりました。

struct base {
  virtual void f();
  virtual void f(int);
};

struct derived : base {
  // using base::f; would solve it
  virtual void f() { ... }
};

おっと-d.f(0);名前検索ではゼロパラメータしか見つからないため、無効になりましたf!usingディレクティブはそれを解決します。(この場合のように)明示的な宣言と同じパラメータータイプと定数を持つ関数宣言をエイリアスする場合f()、明示的な宣言は、using宣言がエイリアスであるものを非表示にすることに注意してください-したがって、両方のf()関数は'この場合、競合します。

これを解決する別の方法は、非仮想インターフェースのイディオムを使用することです。

struct base {
  void f() { do_f(); }
  void f(int) { do_f(0); }

private:
  virtual void do_f();
  virtual void do_f(int);
};

struct derived : base {
private:
  virtual void do_f() { ... }
};

struct derived1 : derived {
private:
  virtual void do_f(int) { ... }
};

これで、d.f(0)d.f()は、どのオブジェクトと呼んでも有効です。

于 2010-03-28T11:09:44.197 に答える
7

残念ながら、あなたが見ている例はあいまいです。

using ::_Filet;

他の人が指摘しているように、using宣言により、指定された名前空間の名前が現在の名前空間で使用可能になります。そのファイルでは、名前空間が開かれていないように見えるため、現在の名前空間がグローバル名前空間であり、グローバル名前空間を::アドレス指定する前に何もないと想定します。したがって、ここでは、名前をグローバル名前空間からグローバル名前空間に移動しているようです。どうしたの?

答えはマクロの使用にあります:

_STD_BEGIN

これはとして定義されnamespace std {ます。したがって、using宣言が行っているのは、それらの名前をstd名前空間に表示することです。そうでない場合は、グローバル名前空間にのみ表示されます。

于 2010-03-28T10:52:25.883 に答える
3

using <some symbol>シンボルをその名前空間から現在の名前空間にプルします。次のコードを想定します。

namespace foo {
  // Assume you want to use std::string, you can either do
  std::string bar;
  // or
  using std::string;
  string bar;
}

ご覧のとおり、名前空間(コードの最初の行)を使用してシンボルを修飾するか、2番目の方法で修飾することができます。頻繁に使用するシンボルの場合、名前空間にそれらをプルすると、コードが少し読みやすくなる傾向がありますが、競合がある場合(たとえば、悪い習慣ですが発生する可能性のある独自fooのクラスが含まれている場合)、適切なもので修飾しますstring名前空間を使用すると、競合を解決できます。

名前空間::は、グローバル名前空間を参照するため、特殊なケースです。この特定のケースでは、参照している関数はC関数であり、CはC ++名前空間を認識していないため、最終的にグローバル名前空間になります。

C ++の名前空間は、シンボルの名前の衝突を回避するための非常に強力なメカニズムであり、C++プログラマーにはそれらを使用することを強くお勧めします。

于 2010-03-28T10:39:29.560 に答える
3

'using'キーワードを使用すると、名前空間から現在の名前空間に名前を取り込むことができます。<namespace name>::<name>名前空間を現在の名前空間に入れずに名前空間内で使用する場合は、次のような形式を使用する必要があります。


std::cout << "Hello World";

が現在の名前空間に組み込まれている場合coutは、次のように使用できます。


cout << "Hello World";

キーワードは次のusingように使用できます。

  • usingディレクティブ(using namespace <namespace name>;)として:

using namespace std;

これにより、名前空間内のすべての名前stdが現在の名前空間になります。

  • 使用宣言として(using <namespace>::<member name>;):

using std::cout;

これにより、std::cout名前のみが現在の名前空間に追加されます。

于 2010-03-28T10:44:33.893 に答える
0

using指定された名前空間の名前を現在の名前空間で使用できるようにします。

于 2010-03-28T12:06:52.710 に答える