2009-04-02 9 views
2

私はまだC++を学んでいますが、以前は自分の名前空間を実際に作成したことはありません。私は彼らと一緒に実験していました。仕事をするのにほとんどのことがありましたが、私はまだできないことがあります。 NameOfClass::methodのようなものを入力せずに、クラス内で静的メソッドを呼び出せるようにしたいと考えています。ここで私はコードは次のようになります考えたものであるが、それはコンパイルに失敗します。C++は長いパスを避けるために名前空間を使用します

ファイルA.h

namespace Test 
{ 
    class A 
    { 
     public: 
      static int foo() { return 42; } 
    }; 
} 

ファイルmain.cpp

#include <iostream> 

#include "A.h" 

using namespace std; 
using namespace Test::A; 

int main() 
{ 
    cout << foo() << endl; 

    return 0; 
} 

は、コンパイラは私を与える:

main.cpp:6: error: ‘A’ is not a namespace-name 
main.cpp:6: error: expected namespace-name before ‘;’ token 
main.cpp: In function ‘int main()’: 
main.cpp:10: error: ‘foo’ was not declared in this scope 

入力しないと何をしようとしているのですか。A::foo

答えて

5

静的メソッドのクラス名を指定する必要はありません。その後

using namespace Test; 

int answerToEverything = A::foo(); 
+0

これはバマーです。 : -/ –

0

いいえ、それはあなたが任意のエレガントなファッションで何をしようとして行うことはできません。あなたが行うことができる最も近いことは、関数に委譲するマクロまたはインライン関数を作成することです。しかし、これらの選択肢の両方はむしろ醜いので、コードサンプルを投稿するつもりはありません。単に弾丸を噛んで全体の名前を指定するか、コードをリファクタリングして静的メソッドがグローバル関数になるようにします。

10

C++では、コンパイラエラーメッセージを慎重に読む必要があります。

最初のエラーは「エラー: 'A'は名前空間名ではありません」であることに注意してください。それは本当です、Aはクラス名です。

using namespace Foo; // brings in all of foo; 
using Bar::Baz // brings in only Baz from Bar 

あなたが書きたい:

2つの良いことを行い
using Test::A; 

:それはあなたが使用するAにもたらし、それが良いである、テストのすべての残りの部分で持っていませんあなたが必要とするものだけを持ち込むべきであるから、あなたが気づいていないものに偶然依存しないようにする必要があるからです。 fooがAで静的であるよう

しかし、あなたはまだ明示:: FOOを参照する必要があります。 (A :: fooに転送する自由な関数を書くのと同じようなことをしない限り、一般的には入力を省くためにのみ行うのは悪い考えです)

宣言を使用しないことをアドバイスする人もいます代わりに、すべての名前を完全に修飾します。

しかし、これは(退屈でエラーが発生しやすい)、リファクタリングの仕方にあります.FooMatic :: Stackクラスを使用するたびに完全修飾され、管理者はあなたの直前barMaticがあなたの会社を買収したので、BarMaticの非常によく似たStackクラスを使用することになります。

はどこでもあなたが完全修飾、あなたは正規表現が正しかった期待して、grepをの多くをやっていると思い持っていました。 using宣言を使用した場合は、あなたの(うまくいけば共有されている)ヘッダーファイルに修正を加えればいいだけです。このように、using宣言は "typedef int ourInt;"のようなものです。またはマニフェスト定数またはconst: "const int FOO = 1;"であり、多くの場所で参照されるものを変更するための1つの場所を提供します。すべての使用時に名前空間を完全修飾すると、その利点が失われます。

逆に、使用指示を使用して名前空間FooMaticを持ち込み、管理者がBarMatic :: Fooを主張していても、BarMatic相当のFooMatic:Bazを使用しなければならない場合、grepがさらに困難になる可能性があります。 Bazが何らかの理由で使えなくなったからです。

したがって、一度に1つのタイプ(クラス、関数、定数)を導入することは、一般に最も不可欠ですが、避けられないものの、未知の変更を防ぐためには最も柔軟です。ほとんどのコーディングと同様に、十分な粒度を維持しながら退屈な繰り返しを最小限に抑えたいとします。

+0

私はあなたが "常にコンパイラのエラーメッセージを慎重に読まなければなりません"と言っています。 – Tom

+0

リファクタリングを行うことができるツールがたくさんあります。正規表現は必要ありません。グローバルな名前空間を汚染するので、私は決して 'using'宣言を使用しません。これは私の心にとってはより悪い問題です。リファクタリングは事実上問題ではありません。 –

0

「ネームスペースを使用する」という虐待を受けてはなりません。これらの名前空間を使用してください!

std::cout << Test::A::foo() << std::endl; 
関連する問題