9

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

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()
{}

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

4

4 に答える 4

12
int FreeFunction(void);  

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

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

definition for an already declared entity in a namespace(たとえば、囲んでいる名前空間で)提供する場合は、完全修飾名である必要があります。

EDIT2:

これがあなたにもう少し明確にする何かです。このコードではディレクティブを使用しないことに注意してください。

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) 、extern指定子(7.1.1)またはリンケージ仕様25(7.5)を含み、初期化子も関数本体も含まず、宣言しますクラス定義(9.4)の静的データメンバー、クラス名宣言(9.1)、opaque-enum-declaration(7.2)、またはtypedef宣言(7.1.3)、using-declaration( 7.3.3)、static_assert-declaration(Clause 7)、attribute-declaration(Clause 7)、empty-declaration(Clause 7)、またはusing-directive(7.3.4)。

于 2010-11-03T07:39:52.333 に答える
2

関数を定義する限り、それを参照するか、行を提供した後に呼び出すFreeFunctionは解決されますが、コンパイラは、名前空間の外部でまったく新しい関数を定義しているかどうか、またはすでに宣言されているを再定義します。コンパイラーは、デフォルトで、まったく新しい関数を定義していると考えます。Test::FreeFunctionusing namespace Test; FreeFunctionTest::FreeFunction

CTest::CTestただし、については、すでにクラスを参照しています。名前空間の外部にTest::CTestクラスまたは名前空間がないため、への参照は明確です。したがって、コンストラクタとデストラクタの定義が名前空間内のクラスを参照していることがわかります。CTestTestCTest::anythingCTest

書く必要があるのは、支払うのは少額だと思いますTest::FreeFunction

お役に立てれば!

于 2010-11-03T07:45:11.547 に答える
1

FreeFunction定義を修飾しない場合、コンパイラは、以前に前方宣言されたTest::FreeFunctionまたは現在の名前空間内の個別のFreeFunctionの実装を提供する必要があるかどうかを確実に認識しません。

一方、CTestという名前を解決する方法は1つしかありません。それは、Test名前空間からのクラス定義です。したがって、完全に認定する必要はありません。

ただし、CTestの名前解決があいまいな場合(たとえば、現在の名前空間にも別のCTestクラスがある場合)、メソッド宣言を完全に修飾する必要があります。

于 2010-11-03T07:44:39.643 に答える
0

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

// in Test.cpp
namespace Test
{
   int FreeFunction()
   {
       return 0;
   }
}
于 2010-11-03T09:44:13.353 に答える