我有一个带有一些类代码的.h文件 - overlay.h
#include<iostream>
#include<boost/thread.hpp>
#include<vector>
#include<boost/asio.hpp>
#include <string>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
#include <boost/tuple/tuple.hpp>
#include<member.h>
using boost::asio::ip::tcp;
class overlay_server{...};
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
现在我将结构移动到另一个名为member.h的新文件 并包含此文件,因此我的类overlay_server可以使用它。 现在,当我构建程序时,我收到错误。
我应该做些什么改变来完成这项工作? 我在SO上读到了关于标题保护的内容,但是无法真正理解如何在这里实现它以解决问题。
---- ----编辑
member.h
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
run.cpp
#include<overlay_server.h>
#include<overlay_client.h>
int main(){
overlay_server overlay_server_(8002);
boost::thread thread_(boost::bind(&overlay_server::member_list_server, overlay_server_));
overlay_client overlay_client_("127.0.0.1",8002);
overlay_client_.member_list_client();
thread_.join();
}
我没有在任何地方重新定义struct。 我有另一个名为overlay_client的类,它也使用struct member。
在我的main函数中,我创建了overlay_server和overlay_client的对象。 现在我的程序只在member.h包含在overlay_server.h中时运行(尽管overlay_server和overly_client中的代码都需要它) 如果它包含在两者中,那么我得到重新定义错误
为什么?
---- ----编辑
我的member.h中的这段代码解决了这个问题 Compile error "'struct' type redefinition" although it's the first definition for it
答案 0 :(得分:1)
您也可以使用pragma
并获得相同的效果。在所有头文件的顶部,写下:
#pragma once
rest of the header
.
.
.
使用包含警卫的方法是用一个包含保护的头文件包围所有内容,如下所示:
// At the very top
#if !defined(SOME_SYMBOL)
#define SOME_SYMBOL
rest of the header
.
.
.
// At the very bottom
#endif // SOME_SYMBOL
现在,选择合理的名称而不是SOME_SYMBOL
非常重要。大多数程序员根据文件名(以及路径和项目名称以及公司/个人名称)创建保护名称。例如,对于位于“[project root”中的名为“some_header.h”(或“SomeHeader.h”)的标头] / include / myproject“,您将保护名称命名为__INCLUDE__MY_PROJECT__SOME_HEADER_H__
。但这只是一个建议;任何独特的符号都可以。
您还可以合并pragma
和包含保护(因为pragma
方法可以改善非常大的项目中的编译时间,但并非所有编译器都支持它。如果你想要他们两个,你会写:
#pragma once
#if !defined(__INCLUDE__MY_PROJECT__SOME_HEADER_H__)
#define __INCLUDE__MY_PROJECT__SOME_HEADER_H__
rest of the header
.
.
.
#endif // __INCLUDE__MY_PROJECT__SOME_HEADER_H__
这没有任何不利影响(据我所知),只有潜在的防止构建错误并使你的构建更快(在大型项目上)。但请注意,包含警卫和#pragma once
的含义是不完全相同。在极少数情况下,您需要使用其中一种,或两种都不使用。
答案 1 :(得分:1)
这是发生了什么事。 你有
member.h
包含在overlay_server.h
和overlay_client.h
现在当你在main.cpp中包含这两个
时就像你在main.cpp中这样做(实际上预处理器扩展如下)
#include"member.h"
#include"member.h"
因此在完全展开后通常会是这样的
struct member{...};
struct member{...}; //redifinition!!
所以编译器将它解析为struct member
的两个定义(因为它将访问member.h两次并读取成员结构的def)。
如何避免这种情况
在member.h中添加此
#ifndef MEMBER_DECL //initially not defined
#define MEMBER_DECL //include guard(now first time you enter this MEMBER_DECL will get defined. so second time compiler comes here it skips this.)
struct member
{
//rest here
};
#endif
现在主要是你有这个
#include"member.h" //when this happens MEMBER_DECL is defined
所以
//#include"member.h" member will not be expanded again hence resolving your redfinition
答案 2 :(得分:0)
如果overlay.h
包含struct member
定义且member.h
也有struct member
定义,则您无法包含member.h
中的overlay.h
。以下是包括警卫工作的方式:
#include<iostream>
#include<boost/thread.hpp>
#include<vector>
#include<boost/asio.hpp>
#include <string>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
#include <boost/tuple/tuple.hpp>
#include<member.h>
#ifndef _H__MEMBER_
#define _H__MEMBER_
using boost::asio::ip::tcp;
class overlay_server{...};
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
#endif
注意#ifndef _H__MEMBER_
和#define _H__MEMBER_
以及#endif
。使用包含警戒,它确保您的标题仅包含一次,因为在第一次包含它之后 H _MEMBER_将已经定义,因此它将跳过定义。您的命名约定可能不同,但通常我按照我的定义执行_H__<HEADER NAME>_
的操作。