0

クラスコードを含む.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のヘッダーガードについて読みましたが、問題を解決するためにここで実装する方法を本当に理解できませんでした。

- - 編集 - -

メンバー.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();
}

どこにも構造体の再定義はありません。構造体メンバーも使用するoverlay_clientという別のクラスがあります。

メイン関数では、overlay_server と overlay_client の両方のオブジェクトを作成します。私のプログラムは、member.h が overlay_server.h に含まれている場合にのみ実行されます (ただし、overlay_server と overly_client の両方のコードで必要です)。両方に含まれている場合、再定義エラーが発生します。

なぜ?

- - 編集 - -

私のmember.hのこのコードは、 コンパイルエラー「 'struct' type redefinition」の問題を解決しますが、それは最初の定義です

4

3 に答える 3

1

pragmaa を使用して同じ効果を得ることもできます。すべてのヘッダー ファイルの先頭に、次のように記述します。

#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非常に重要です. ほとんどのプログラマーは、ファイル名 (およびパスとプロジェクト名と会社/個人名) に基づいてガード名を作成します。たとえば、"[プロジェクト ルート]/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だけです。ごくまれに、どちらか一方を使用するか、どちらも使用しない必要がある場合があります。

于 2013-05-24T04:30:04.310 に答える
1

これが起こっていることです。あなたが持っている

member.h

に含まoverlay_server.hれるoverlay_client.h

これら2つをmain.cppに含めると

main.cppでこれを行っているようなものです(実際にはプリプロセッサは以下のように展開されます)

#include"member.h"
#include"member.h"

したがって、通常、完全な展開後はこのようになります

struct member{...};
struct member{...};    //redifinition!!

そのため、コンパイラはそれを の 2 つの定義として解析しますstruct member(member.h に 2 回アクセスし、メンバー構造体の定義を読み取るため)。

これを避けるために何をすべきか

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 
于 2013-05-24T04:33:47.420 に答える
0

overlay.hに定義が含まれていて、struct member定義member.hもある場合、 fromstruct memberを含めることはできません。ただし、インクルードガードがどのように機能するかは次のとおりです。member.hoverlay.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_ が既に定義されているため、ヘッダーが 1 回だけインクルードされるようになり、定義がスキップされます。_H__<HEADER NAME>_命名規則は異なる場合がありますが、通常、私は自分の定義に従って 何かを行います。

于 2013-05-24T04:07:21.487 に答える