错误C2011:'member':'struct'类型重定义将结构移动到新的头文件

时间:2013-05-24 03:58:08

标签: c++ boost

我有一个带有一些类代码的.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

3 个答案:

答案 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.hoverlay_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>_的操作。