名前空間、クラス、および無料関数 - 完全に資格のある名前が必要なのはいつですか

StackOverflow https://stackoverflow.com/questions/4084972

質問

以下の私の例では、リンカーエラーを回避するためにCPPの自由関数の名前を完全に修飾する必要があるのはなぜですか?違いを説明できますか?

ctest.h:

namespace Test
{
    int FreeFunction();

    class CTest
    {
        public:
            CTest();
            ~CTest();
    };
}

ctest.cpp:

#include "ctest.h"

using namespace Test;

// int FreeFunction()     -> undefined reference error
int Test::FreeFunction()  -> works just fine
{
    return 0;
}

CTest::CTest()                -> no need to fully qualify name, i.e. Test::CTest
{}

CTest::~CTest()
{}

お時間をいただきありがとうございます。

役に立ちましたか?

解決

int FreeFunction(void);  

以下は定義ですが、単なる宣言です。

class CTest 
{ 
    public: 
        CTest(); 
        ~CTest(); 
}; 

提供したい場合 definition for an already declared entity in a namespace (例えば、名前空間を囲む)、それは完全に資格のある名前でなければなりません。

編集2:

これがあなたにもっと明確になるものです。このコードでディレクティブを使用しないでください。

namespace Test { 
    int FreeFunction(void);   // declare

    class CTest;              // declare
} 

int Test::FreeFunction(){return 0;} // define
class Test::CTest{            // define
};

int main(){}

編集3:宣言対定義(C ++ 0x)$ 3.1/2-

宣言は定義です 関数の本体を指定せずに関数を宣言しない限り(8.4), 、それは外部指定子(7.1.1)またはリンケージ仕様25(7.5)を含み、イニシャルイザーも関数体も含まれていません。クラス定義(9.4)の静的データメンバーを宣言します。 クラス名宣言(9.1)です, 、それは不透明なenum declaration(7.2)であるか、Typedef宣言(7.1.3)、使用法(7.3.3)、static_assert-Declaration(節7)、属性declaration(句ase)です。 7)、空の宣言(条項7)、または使用法(7.3.4)。

他のヒント

その間 FreeFunction に解決します Test::FreeFunction もし、あんたが それを参照するか、電話してください 提供した後 using namespace Test; ライン、限り 定義 関数が進むと、コンパイラはあなたが定義しているかどうかを知る方法がありません まったく新しい機能 FreeFunction 名前空間の外、または既に宣言されたものを定義しているかどうか Test::FreeFunction. 。コンパイラは、まったく新しい関数を定義していると考えるデフォルトです。

にとって CTest::CTest, しかし、あなたはすでにです 参照 クラス Test::CTest, 、そしてクラスや名前空間がないので CTest の外側 Test 名前空間、まあ、への参照 CTest::anything 明確です。したがって、コンストラクターとデストラクタの定義は、namespaceクラスを指していることを知っています CTest.

私はそれが支払う、書く必要があるのは小さな価格だと思います Test::FreeFunction.

お役に立てれば!

FreeFunctionの定義を修飾しない場合、コンパイラは、以前にフォワードで宣言されたテスト:: FreeFunctionまたは現在の名前空間での別のフリー機能のために実装を提供することを確実に知らないことを確認しません。

一方、テスト名空間のクラス定義として、名前ctestを解決する方法は1つしかありません。したがって、完全に資格を付ける必要はありません。

ただし、CTEST名の解像度があいまいである場合(現在の名前空間に別のCTESTクラスもあるとすると)、メソッド宣言を完全に認定する必要があります。

関数を実装する場合、通常、名前空間を開くことが望ましいと思います。あなたがそれらを再び開けることができることを忘れないでください...

// in Test.cpp
namespace Test
{
   int FreeFunction()
   {
       return 0;
   }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top