c++ - 制作 Boost::Asio chat_server 示例的头文件会给我“找到一个或多个定义的符号”错误
问题描述
我是 c++ 和 boost 库的新手,试图通过从这个例子中制作三个单独的文件来学习头文件。https://www.boost.org/doc/libs/1_70_0/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp chat_message.hpp 在这里虽然我不认为这会导致问题。https://www.boost.org/doc/libs/1_70_0/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp
目标是将示例分成三个部分。
- 主文件
- chat_server.h - 声明的头文件
- chat_server.cpp - 实现
这是我的实现,但我遇到了两个错误。
- 错误列表 -
LNK1169 > One or more multiple defined symbols found > File-> main.exe
LNK2005 > $dummy_return@asio@boost@@YAXXZ) already defined in chat_server.obj > file-> main.obj
输出
Build started...
1>------ Build started: Project: main, Configuration: Debug Win32 ------
1>main.obj : error LNK2005: "void __cdecl boost::asio::dummy_return<void>(void)" (??$dummy_return@X@asio@boost@@YAXXZ) already defined in chat_server.obj
1>C:\Users\Offline User\source\repos\main\Debug\main.exe : fatal error LNK1169: one or more multiply defined symbols found
1>Done building project "main.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
示例代码在分成三个之前运行良好。我不知道这是否与 typedef 或 virtual 有关,因为其他类和方法对我来说很容易理解(根据我在网上学到的)。请在这里帮助我,让我知道我在这里缺少什么?谢谢。
- 主文件
#include "chat_server.h"
int main(int argc, char* argv[])
{
try
{
if (argc < 2)
{
std::cerr << "Usage: chat_server <port> [<port> ...]\n";
return 1;
}
boost::asio::io_context io_context;
std::list<chat_server> servers;
for (int i = 1; i < argc; ++i)
{
tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[i]));
servers.emplace_back(io_context, endpoint);
}
io_context.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
- 聊天服务器.h
#ifndef CHAT_SERVER_H
#define CHAT_SERVER_H
#include <cstdlib>
#include <deque>
#include <iostream>
#include <list>
#include <memory>
#include <set>
#include <utility>
#include <boost/asio.hpp>
#include "chat_message.hpp"
using boost::asio::ip::tcp;
//----------------------------------------------------------------------
typedef std::deque<chat_message> chat_message_queue;
//----------------------------------------------------------------------
class chat_participant
{
public:
virtual ~chat_participant() {};
virtual void deliver(const chat_message& msg) = 0;
};
typedef std::shared_ptr<chat_participant> chat_participant_ptr;
//----------------------------------------------------------------------
class chat_room
{
public:
void join(chat_participant_ptr participant);
void leave(chat_participant_ptr participant);
void deliver(const chat_message& msg);
private:
std::set<chat_participant_ptr> participants_;
enum { max_recent_msgs = 100 };
chat_message_queue recent_msgs_;
};
//----------------------------------------------------------------------
class chat_session
: public chat_participant,
public std::enable_shared_from_this<chat_session>
{
public:
chat_session(tcp::socket socket, chat_room& room);
void start();
void deliver(const chat_message& msg);
private:
void do_read_header();
void do_read_body();
void do_write();
tcp::socket socket_;
chat_room& room_;
chat_message read_msg_;
chat_message_queue write_msgs_;
};
//----------------------------------------------------------------------
class chat_server
{
public:
chat_server(boost::asio::io_context& io_context,
const tcp::endpoint& endpoint);
private:
void do_accept();
tcp::acceptor acceptor_;
chat_room room_;
};
#endif
- 聊天服务器.cpp
#include "chat_server.h"
void chat_room::join(chat_participant_ptr participant)
{
participants_.insert(participant);
for (auto msg : recent_msgs_)
participant->deliver(msg);
}
void chat_room::leave(chat_participant_ptr participant)
{
participants_.erase(participant);
}
void chat_room::deliver(const chat_message& msg)
{
recent_msgs_.push_back(msg);
while (recent_msgs_.size() > max_recent_msgs)
recent_msgs_.pop_front();
for (auto participant : participants_)
participant->deliver(msg);
}
//----------------------------------------------------------------------
chat_session::chat_session(tcp::socket socket, chat_room& room)
: socket_(std::move(socket)),
room_(room)
{
}
void chat_session::start()
{
room_.join(shared_from_this());
do_read_header();
}
void chat_session::deliver(const chat_message& msg)
{
bool write_in_progress = !write_msgs_.empty();
write_msgs_.push_back(msg);
if (!write_in_progress)
{
do_write();
}
}
void chat_session::do_read_header()
{
auto self(shared_from_this());
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.data(), chat_message::header_length),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec && read_msg_.decode_header())
{
do_read_body();
}
else
{
room_.leave(shared_from_this());
}
});
}
void chat_session::do_read_body()
{
auto self(shared_from_this());
boost::asio::async_read(socket_,
boost::asio::buffer(read_msg_.body(), read_msg_.body_length()),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
room_.deliver(read_msg_);
do_read_header();
}
else
{
room_.leave(shared_from_this());
}
});
}
void chat_session::do_write()
{
auto self(shared_from_this());
boost::asio::async_write(socket_,
boost::asio::buffer(write_msgs_.front().data(),
write_msgs_.front().length()),
[this, self](boost::system::error_code ec, std::size_t /*length*/)
{
if (!ec)
{
write_msgs_.pop_front();
if (!write_msgs_.empty())
{
do_write();
}
}
else
{
room_.leave(shared_from_this());
}
});
}
//----------------------------------------------------------------------
chat_server::chat_server(boost::asio::io_context& io_context,
const tcp::endpoint& endpoint)
: acceptor_(io_context, endpoint)
{
do_accept();
}
void chat_server::do_accept()
{
acceptor_.async_accept(
[this](boost::system::error_code ec, tcp::socket socket)
{
if (!ec)
{
std::make_shared<chat_session>(std::move(socket), room_)->start();
}
do_accept();
});
}
解决方案
见https://github.com/chriskohlhoff/asio/pull/584
include/boost/asio/impl/use_awaitable.hpp
有错误,dummy_return
应标明inline
。
改变:
template <>
void dummy_return()
{
}
至:
template <>
inline void dummy_return()
{
}
推荐阅读
- regex - 如何从Python中的文件中删除字符串直到行尾?
- java - 在 onActivityCreated() 中获取 RecyclerView 视图时出错
- css - 为什么第 n 个子颜色在 markdown++ 查看器中不起作用?
- c# - Mongodb C# 驱动程序执行字符串包含对嵌入文档中的属性的查询
- selenium - TestNG中Appium测试用例的顺序执行导致测试用例失败
- r - 在 R 中创建嵌套列表
- visual-studio-code - 如何让vscode在保存时自动重命名文件?
- android - 如何使用 Firestore 集合中的经度和纬度在地图上显示带有标记的位置?
- ruby - postgresql 中枚举类型列的包含过滤
- java - 为什么android程序不能在我的手机上运行(它可以在虚拟手机上正常运行)