朋友功能的未解析外部符号

时间:2013-03-15 11:00:30

标签: c++ dll linker unresolved-external

首先是我的代码布局:

A.H

class STORAGE_CLASS_DECLARATOR A : public PureVirtual
{
   some member functions, all working;
   void someFunctionCallingOperator<<();
   friend std::ostream& operator << (std::ostream &, A *);
}

A.cpp

std::ostream& operator << (std::ostream & out, A * a){...}
void A::someFunctionCallingOperator<<(){...}

其中Storage_xxx_declarators是declspec的宏。我已经尝试过使用和不使用声明器的朋友函数都无济于事。

我在运算符上得到一个未解析的外部符号&lt;&lt;功能

根据我的理解,这可能是由于:

  1. 该函数没有正文,这显然不正确,因为文件肯定已经解析为正在运行的其他函数。
  2. 符号未正确导出。同样,我对如何发生这种情况感到茫然,并且在实际情况中,运营商&lt;&lt;对于A这里实际上调用运算符&lt;&lt;对于另一个B类,也为该函数显示相同的错误。因此,必须在某个时候解析A的定义。
  3. 我意识到链接是一个单独的阶段,我必须做一些非常简单的错误,但我现在已经盯着看了一段时间,并且无法从理论上推断出为什么会发生这种情况,所以我转向SO寻求帮助< / p>

    谢谢你, AK

3 个答案:

答案 0 :(得分:3)

根据您的评论,我认为您的设置是这样的:

A.H

namespace NN {

class STORAGE_CLASS_DECLARATOR A : public PureVirtual
{
   some member functions, all working;
   void someFunctionCallingOperator<<();
   friend std::ostream& operator << (std::ostream &, A *);
}

}

A.cpp:

using namespace NN;

std::ostream& operator << (std::ostream & out, A * a){...}
void A::someFunctionCallingOperator<<(){...}

这是一个非常常见的设置,但我不鼓励任何人使用它,因为它会导致您现在拥有的类型问题。让我们看看A.cpp中发生了什么:

在解析A::someFunctionCallingOperator的定义时,全局命名空间中没有A,因此会考虑using - ed名称空间,而A将被解析为NN::A }。

然而,在解析operator<<的定义时,什么都没有表明应该将运算符放入名称空间NN。所以这很高兴地定义了全局命名空间中的operator<<,它与NN::operator<<中的朋友声明引入的{{1>} 绝不相关。稍后,当您在A.h内使用<<时,someFunctionCallingOperator(已在NN::operator<<中声明)通过参数依赖查找找到,因此使用它。最后,链接器正在抱怨它从未定义过。

解决此问题的正确方法是在A.h中停止using namespace NN并将内容正确地包含在命名空间中,就像在头文件中一样:

A.cpp

答案 1 :(得分:1)

简答:确保运算符的返回类型和参数在定义和实现方面都是相同的。

答案稍长:

您似乎省略了运算符的返回类型。您的朋友函数定义包含您的宏,但实现标识ostream&的返回类型。如果您的宏中未包含ostream&,则可能会导致无法解析的外部符号错误。

您还省略了实现中的参数,如果您尝试将运算符与参数一起使用(这对<<来说是正常的),也会导致未解决的外部符号错误。编译器将使用单个参数(以及<<返回类型)查找ostream&的实现,但只会找到带有空参数列表的operator<<的实现。

答案 2 :(得分:0)

我通过将方法放在同一名称空间

中来解决问题