9

在下面的示例中,为什么我必须完全限定 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()
{}

感谢您的时间和帮助。

4

4 回答 4

12
int FreeFunction(void);  

只是一个声明,而下面是一个定义。

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

如果你想提供definition for an already declared entity in a namespace(例如在封闭的命名空间中),它必须是完全限定的名称。

编辑2:

这里有一些东西可以让你更清楚。注意此代码中没有 using 指令。

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),它是不透明枚举声明 (7.2),或者它是 typedef 声明 (7.1.3),使用声明 ( 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::FreeFunction您是否在提供该行后引用它或调用它,但就定义函数而言,编译器无法知道您是否在任何命名空间之外定义了一个全新的函数,或者您是否重新定义已经声明的. 编译器默认认为您正在定义一个全新的函数。using namespace Test; FreeFunctionTest::FreeFunction

但是,对于CTest::CTest,您已经在引用class ,并且由于在命名空间之外Test::CTest没有类或命名空间,所以对的引用是明确的。所以它知道构造函数和析构函数定义引用了命名空间中的类。CTestTestCTest::anythingCTest

我认为这是一个很小的代价,不得不写Test::FreeFunction

希望这可以帮助!

于 2010-11-03T07:45:11.547 回答
1

如果您不限定 FreeFunction 定义,则编译器无法确定您想要为先前前向声明的 Test::FreeFunction 或当前命名空间中的单独 FreeFunction 提供实现。

另一方面,只有一种方法可以解析名称 CTest - 作为来自 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 回答