【发布时间】:2011-12-22 21:54:38
【问题描述】:
我正在尝试以标准方式重载 operator<<。我有一个名为 SymbolTable 的类,它位于一个名为 SymbolTable.h 的文件中,如下所示:
namespace Compaler // It's a pun; don't ask
{
class SymbolTable
{
public:
// ...
friend ostream& operator<<(ostream &out, const SymbolTable &table);
private:
vector<map<int, Symbol*> > mSymbols;
};
// ...
}
operator<< 的实现访问了 SymbolTable 的一些私有成员。这是实现的签名,以证明它与前向声明的签名没有区别(我复制粘贴它以确保我不会发疯。)
ostream& operator<<(ostream &out, const SymbolTable &table)
{ ... }
如果我将实现放在第二个 ... 所在的 SymbolTable.h 中,我会收到以下链接器错误:
ld: 重复符号 Compaler::operator&, Compaler::SymbolTable const&)in /var/folders/kt/pl6qd1490fn3yqxfpg64jyr80000gn/T//ccstrYnU.o 和 /var/folders/kt /pl6qd1490fn3yqxfpg64jyr80000gn/T//ccDQFiyK.o 用于架构 x86_64
但是,如果我把它放在 SymbolTable.cpp 中,我的 SymbolTable 成员实现的其余部分都在其中,代码甚至无法编译;我收到与访问私人成员相关的错误,表明友谊未被识别:
../SymbolTable/SymbolTable.h:在函数'std::ostream& operator, Compaler::Symbol*, std::less, std::allocator >>, std::allocator, std: :allocator >, Compaler::Symbol*> > >, std::allocator, std::allocator >, Compaler::Symbol*, std::less, std::allocator >>, std::allocator, std::分配器 >, Compaler::Symbol*> > > > > Compaler::SymbolTable::mSymbols' 是私有的 ../SymbolTable/SymbolTable.cpp:98:错误:在此上下文中
我做错了什么?
答案总结:
感谢 Seth Carnegie 和 Daniel R. Hicks,我已经弄明白了。为了将来可能犯同样错误的人的利益,我将在我的问题中总结答案,因为在 cmets 中有很多来回。
第一个(在 SymbolTable.h 中实现时出现重复符号)问题发生是因为我试图同时编译和链接两个包含 SymbolTable.h 的文件。我一直在误解#ifdef 包括警卫的工作方式;也就是说,它们只会阻止代码在一个文件中包含两次,但如果您尝试链接两个都包含来自第三个文件的代码的文件,它们将无济于事。
第二个问题是当我将 operator<< 实现放在 SymbolTable.cpp 文件中时,我忘记将它放在 Compaler 命名空间中。
【问题讨论】:
-
将
inline添加到头文件中的函数定义中,这应该会使编译器对多重定义闭嘴。 -
您确定命名空间正确吗?作为一种解决方法,您可以将函数定义与友谊线一起放在类定义中......但这不是答案。
-
在第一种情况下,您会收到重复符号错误,因为 SymbolTable.H 包含在多个 .C 文件中。
-
在我看来你已经将它包含在 SymbolTable.cpp 和 SymbolTableTest.cpp 中。
-
愚蠢的问题:当您将
operator <<定义放在.CPP 文件中时,您是否使用SymbolTable适当地指定命名空间?如果您不以某种方式提供命名空间,SymbolTable的出现似乎与 .H 文件中的完全不同。
标签: c++ linker operator-overloading friend access-control