1

首先是我的代码布局:

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 的宏。我已经尝试过使用和不使用声明符的朋友功能都无济于事。

我在 operator<< 函数上得到一个未解析的外部符号。

据我了解,这可能是由于:

  1. 该函数没有正文,这显然是不正确的,因为该文件肯定会针对正在工作的其他函数进行解析。
  2. 符号未正确导出。同样,我不知道这是如何发生的,在实际场景中,此处 A 的 operator<< 实际上为另一个 B 类调用了 operator<<,并且该函数也显示了相同的错误。因此,A 的定义必须在某个时候被解析。

我意识到链接是一个单独的阶段,而且我一定是在做一些非常简单的错误,但我已经凝视了一段时间,无法从理论上解释为什么会发生这种情况,所以我转向 SO 寻求帮助

谢谢你,AK

4

3 回答 3

3

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

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<<,根本没有任何迹象表明应该将运算符放入 namespace NN。所以这很高兴地定义operator<<全局命名空间中,这与. 后来在使用inside的时候,(已经在 in 中声明过)是通过参数依赖查找找到的,所以就使用了。最后,链接器正确地抱怨它从未被定义过。NN::operator<<A.h<<someFunctionCallingOperatorNN::operator<<A.h

解决这个问题的正确方法是停止using namespace NNA.cpp正确地将内容包含在命名空间中,就像在头文件中所做的那样:

namespace NN {

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

}
于 2013-03-15T13:40:07.763 回答
1

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

稍微长一点的答案:

看来您已经省略了运算符的返回类型。您的朋友函数定义包括您的宏,但实现标识ostream&. 如果ostream&未包含在您的宏中,这可能会导致未解决的外部符号错误。

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

于 2013-03-15T11:08:53.567 回答
0

我通过将方法放在同一个命名空间中解决了这个问题

于 2018-04-06T17:43:57.097 回答