3

为什么会出现链接器错误?

/*
test.cpp
© Andrey Bushman, 18 Jun 2013
*/
//--------------------------------------------
#include <exception>
#include <iostream>
using namespace std;
//--------------------------------------------
namespace Bushman{
//--------------------------------------------
    class MyClass{
    public:
        MyClass();
    };
//--------------------------------------------
    MyClass::MyClass(){
        void func(); // declaration
        func(); // call
    }
//--------------------------------------------
    void func(){ // definition
        cout << "Ping..." << endl;
    }
}
//============================================
int main()
try{
    namespace B = Bushman;
    B::MyClass a;
}
catch(exception& e){
    cerr << e.what() << endl;
    return 1;
}
catch(...){
    cerr << "Unknown exception." << endl;
    return 2;
}

结果(由 MS Visual Studio 2012 提供):

C:\bs\13>cl test.cpp /EHsc
Microsoft (R) C/C++ Optimizing Compiler
Version 17.00.51106.1 for x64 Copyright (C) Microsoft Corporation. All
rights reserved.

test.cpp
Microsoft (R) Incremental Linker Version 11.00.51106.1
Copyright (C) Microsoft Corporation. All rights reserved.

/out:test.exe test.obj test.obj : error LNK2019: unresolved external
symbol "void __cdecl func(void)" ( ?func@@YAXXZ) referenced in
function "public: __cdecl Bushman::MyClass::MyClass( void)"
(??0MyClass@Bushman@@QEAA@XZ) test.exe : fatal error LNK1120: 1
unresolved externals

C:\bs\13>

谢谢你。

4

3 回答 3

3
namespace Bushman{
    MyClass::MyClass(){
        void func(); // declaration
        func(); // call
    }
    //--------------------------------------------
    void func(){ // definition
        cout << "Ping..." << endl;
    }
}

func()MyClass构造函数中声明。这应该func()与您在命名空间中定义的相同Bushman;但似乎你的编译器弄错了。通常在另一个函数或构造函数中声明一个函数被认为是不好的做法。相反,您应该直接在您想要的范围内声明函数。在这种情况下,您需要func()在命名空间内进行前向声明Bushman

namespace Bushman{
    void func(); // declaration

    MyClass::MyClass(){
        func(); // call
    }

    //--------------------------------------------
    void func(){ // definition
        cout << "Ping..." << endl;
    }
}

或者,您可以将代码拆分为单独的 .h 和 .cpp 文件。事实上,这是理想的。我建议func()func.cpp. func.h类似地把MyClass声明myclass.hMyClass定义放在myclass.cpp. 现在myclass.cpp应该`#include“func.h”。

以这种方式使用头文件可以让您对前向声明进行微调控制,并确保在需要时定义所有内容。

于 2013-06-18T15:33:05.223 回答
3

看起来您的编译器错误地将名称引入全局命名空间,而不是BushmanC++11 3.5/7 指定的最内层封闭命名空间 ( ):

当没有发现具有链接的实体的块范围声明引用其他声明时,则该实体是最内层封闭命名空间的成员。

代码在 GCC 上按预期编译:http: //ideone.com/PR4KVC

您应该能够通过在正确的命名空间中声明函数来解决该错误,然后再(或代替)在构造函数的块范围中声明它。但是,我无权访问您的编译器来测试它。

于 2013-06-18T15:48:01.183 回答
1

你在声明一个函数

  void func()

哪个遮蔽了方法

void MyClass::func()

所以你的调用是调用未定义的函数,而不是方法。

于 2013-06-18T15:26:07.957 回答