未定义对运算符的引用<<
undefined reference to operator<<
我有一个带有私人朋友运算符的常规类(不是模板<<
它的声明是:
std::ostream& operator<<(std::ostream& out, const Position& position);
在CPP文件中,它的定义是:
std::ostream& operator<<(std::ostream& out, const Position& position)
{
out << position.getXPoint() << "," << position.getYPoint();
return out;
}
它正在编译然后链接到使用它的主函数,但是当我使用它时,我得到了一个未定义的引用......
但是,当我将定义添加到主 cpp 文件的顶部并删除朋友声明时,它工作正常......
这是我如何在我的主函数中使用它的
std::cout << node->getPosition() << std::endl;
不多也不少...
这是链接器错误
/home/luke/Desktop/pathfinder/parse_world.cpp:34: 未定义引用 'pathfinder::operator<<(std::ostream&, pathfinder::P osition const&)'
这是类标题...
#ifndef PATHFINDER_H
#define PATHFINDER_H
#include <ostream>
#include <istream>
#include <list>
#include <vector>
#include <stdexcept>
#include <cstring>
namespace pathfinder
{
class Node;
typedef unsigned int GCost;
typedef std::vector<std::vector<Node*> > World;
typedef std::vector<Node*> WorldRow;
class Position
{
public:
typedef unsigned int point_type;
private:
point_type* xPoint_;
point_type* yPoint_;
friend std::ostream& operator<<(std::ostream& out, const Position& position);
public:
Position(const point_type& xPoint = 0, const point_type& yPoint = 0);
Position(const Position& position);
Position(Position&& position);
~Position();
Position& operator=(const Position& position);
Position& operator=(Position&& position);
point_type getXPoint() const;
point_type getYPoint() const;
void setXPoint(const point_type& xPoint);
void setYPoint(const point_type& yPoint);
};
class Node
{
private:
bool* isPassable_;
bool* isStartingNode_;
bool* isTargetNode_;
Position* position_;
GCost* additionalGCost_;
Node* parent_;
public:
Node(const bool& isPassable = true, const bool& isStartingNode = false, const bool& isTargetNode = false, const Position& position = Position(0,0), const GCost& additionalGCost = 0, Node* parent = nullptr);
Node(const Node& node);
Node(Node&& node);
~Node();
Node& operator=(const Node& node);
Node& operator=(Node&& node);
bool isPassable() const;
bool isStartingNode() const;
bool isTargetNode() const;
Position getPosition() const;
GCost getAdditionalGCost() const;
Node* getParent() const;
void setAsPassable(const bool& isPassable);
void setAsStartingNode(const bool& isStartingNode);
void setAsTargetNode(const bool& isTargetNode);
void setPosition(const Position& position);
void setAdditionalGCost(const GCost& additionalGCost);
void setParent(Node* parent);
};
class WorldHelper
{
public:
static World fromStream(std::istream& input);
static void syncPositions(World& world);
static void uninitializeWorld(World& world);
static Node* findStartingNode(const World& world);
static Node* findTargetNode(const World& world);
};
class Pathfinder
{
public:
virtual std::list<Node*> operator()(World& world) const = 0;
};
};
#endif //PATHFINDER_H
现在删除好友声明后,我收到错误消息,例如:
无法将"std::ostream {aka std::basic_ostream}"lvalue 绑定到"std::basic_ostream&&"
它与 std::cout 语句发生在同一行...
那么,这到底是怎么回事...
提前致谢
我的猜测,从描述中可以看出,您正在声明两个operator<<
但只定义一个。例如:
namespace A {
struct B {
friend std::ostream& operator<<( std::ostream&, B const & ); // [1]
};
}
std::ostream& operator<<( std::ostream& o, A::B const & ) { // [2]
return o;
}
行 [1] 声明了一个可以通过 ADL 在类型 B
上找到的A::operator<<
函数,但 [2] 声明并定义了::operator<<
。当编译器看到代码时:
A::B b;
std::cout << b;
它使用 ADL 并查找A::operator<<
(从 friend 声明中)并使用它,但该函数未定义。如果删除 friend
声明,则会在全局命名空间中声明和定义 operator<<
的单个实例,并且可以通过常规查找找到该实例。
另请注意,如果程序中存在 using 指令,这可能更难发现,因为 [2] 中的定义可能不会显式命名参数的 A
命名空间。这也可以解释您可以定义该类型的其余成员:
// cpp [assume that the definition of B contained a member f
using namespace A;
void B::f() {
}
B::f
的定义(在代码中)驻留在全局命名空间中,但由于 using 指令,B
将在 A
命名空间中找到,类型说明符等效于在解析B
后A::B
使定义等效于 void ::A::B::f() {}
的原因。对于免费功能,这不会发生。
我建议您避免使用指令,因为它们允许像这样的细微错误。另请注意,您实际上可以在命名空间中显式定义运算符(但您还需要在命名空间中声明它:
namespace A {
struct B { friend std::ostream& operator<<( std::ostream&, B const & ); };
std::ostream& operator<<( std::ostream&, B const & );
}
std::ostream& A::operator<<( std::ostream& o, B const & ) {
return o;
}
这个技巧(通过完全限定来定义其自然命名空间之外的自由函数)有时用于避免隐式声明函数的定义,这容易出现这种类型的错误。例如,如果您在正确的命名空间中定义了运算符,但签名略有不同:
namespace A {
struct B {
friend std::ostream& operator<<( std::ostream&, B const & ); // [1]
};
std::ostream& operator<<( std::ostream&, B & ) { // [3]
return o;
}
}
[3] 中的定义也是一个声明,但它声明的函数与 [1] 中声明的函数不同,您最终可能会挠头问为什么链接器找不到 [1]。
大卫对这个问题给出了很好的答案。 在这里,我只是提供一个易于理解的示例。
在我的头文件中:
namespace BamTools {
class SomeBamClass {
.....
public:
friend std::ostream& operator<<(std::ostream& ous, const SomeBamClass& ba);
.....
}
}
在 cpp 文件中:
using namespace BamTools; // this work for Class member function but not friends
using namespace std;
........
std::ostream& operator<<(std::ostream &ous, const SomeBamClass &ba) {
// actual implementation
return ous;
}
当您尝试从自己的应用程序链接到此库时,上面将为您提供对运算符<<(.., const SomeBamClass&) 的未定义引用,因为它是命名空间之外运算符的声明和实现。
undefined reference to `BamTools::operator<<(std::ostream&, BamTools::SomeBamClass const&)'
唯一对我有用的是将命名空间封闭添加到实现文件中的 friend 函数中:
namespace BamTools {
std::ostream& operator<<(std::ostream &ous, const SomeBamClass &ba) {
...
return ous;
}
}
用。。。BamTools::operator<<(..., const BamTools::SomeBamClass&) 将导致我的 g++ 5.4.0 的编译器错误。
- 将对象数组的引用传递给函数
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 何时在引用或唯一指针上使用移动语义
- 如何在c++中使用引用实现类似python的行为
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 编译C++时未定义的引用
- Ctypes wstring通过引用传递
- 呼叫运营商<<临时
- c++r值引用应用于函数指针
- 理解c++中的引用
- C++取消引用指针.为什么会发生变化
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 我的项目不会像"undefined reference to `grpc::g_core_codegen_interface'"那样使用未定义的引用错误进行编译
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 强制转换为引用类型
- 引用一个已擦除类型(void*)的指针
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 具有默认值的引用获取函数
- 如何使用基类指针引用派生类成员