1

my_template_library.hで使用する必要がある場合、私のプロジェクトはこの設定に似ていますmain_class.h

main.cpp

#include "main_class.h"

int main()
{
    MainClass m;
    return m.exec();
}

main_class.h

#ifndef MAIN_CLASS_H
#define MAIN_CLASS_H

#include "my_template_library.h"

class MainClass {
public:
    MainClass();
    int exec();
};

#endif // MAIN_CLASS_H

main_class.cpp

#include <iostream>

#include "main_class.h"

MainClass::MainClass(){}

int MainClass::exec()
{
    std::cout << "exec!" << std::endl;
    return 0;
}

my_template_library.h

#ifndef MY_TEMPLATE_LIBRARY_H
#define MY_TEMPLATE_LIBRARY_H

#include <iostream>

//#pragma message ("I'm being included past the include guards!")

class MyTemplateLibrary
{
public:
    MyTemplateLibrary();

    void function();
};

MyTemplateLibrary::MyTemplateLibrary(){}

void MyTemplateLibrary::function()
{
    std::cout << "function called!" << std::endl;
}

#endif // MY_TEMPLATE_LIBRARY_H

.h私が書いたテンプレートヘッダーのみのライブラリでは、最初にクラス内のすべてを宣言してから、クラスをと.cppコードに分離するときに通常行うように、クラスの外側にすべてを定義しますが.cpp、 の最後にファイルが追加され、.hインクルード内に警備員。テンプレート ライブラリが 1 回だけ含まれている限り、これは問題なく機能しましたが、それ以上のものが含まれるようになると、非常に紛らわしい問題が発生しました。

$ g++ -o test main.cpp main_class.h main_class.cpp my_template_library.h 
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/ccZikorv.o:main.cpp:(.text+0x0): first defined here
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/ccZikorv.o:main.cpp:(.text+0x0): first defined here
/tmp/ccuFlEDZ.o: In function `MyTemplateLibrary::function()':
main_class.cpp:(.text+0xa): multiple definition of `MyTemplateLibrary::function()'
/tmp/ccZikorv.o:main.cpp:(.text+0xa): first defined here
collect2: error: ld returned 1 exit status

何が起こっているのか混乱しています。これを理解するために my_template_library.h にを追加しました#pragma message。これはコード内でコメントアウトされています。コメントを外してコードを実行すると、

$ g++ -o test main.cpp main_class.h main_class.cpp my_template_library.h 
In file included from main_class.h:4:0,
                 from main.cpp:1:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
In file included from main_class.h:4:0:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
In file included from main_class.h:4:0,
             from main_class.cpp:3:
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
my_template_library.h:6:63: note: #pragma message: I'm being included past the include guards!
 #pragma message ("I'm being included past the include guards!")
                                                           ^
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/cc4XSnui.o:main.cpp:(.text+0x0): first defined here
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::MyTemplateLibrary()':
main_class.cpp:(.text+0x0): multiple definition of `MyTemplateLibrary::MyTemplateLibrary()'
/tmp/cc4XSnui.o:main.cpp:(.text+0x0): first defined here
/tmp/ccmawdhP.o: In function `MyTemplateLibrary::function()':
main_class.cpp:(.text+0xa): multiple definition of `MyTemplateLibrary::function()'
/tmp/cc4XSnui.o:main.cpp:(.text+0xa): first defined here
collect2: error: ld returned 1 exit status

したがって、ヘッダー ファイルは次の方法でインクルードされます。

  1. main.cpp -> main_class.h
  2. main_class.h
  3. main_class.cpp -> main_class.h
  4. my_template_library.h (単独で?)

だから、私の質問は次のとおりです。

  1. インクルードガードが役に立たないのはなぜですか?
  2. これを防ぐにはどうすればよいですか?
4

1 に答える 1

6

インクルードガードが役に立たないのはなぜですか?

インクルード ガードは、同じコンパイル ユニット内の冗長なコードを防ぎます。

同じ関数定義を保持していると主張する異なるコンパイル ユニットに関するリンカ エラーが発生しています。

これを防ぐにはどうすればよいですか?

One Definition Ruleinlineに違反しないように、これらの非テンプレート メンバー関数を作成する必要があります。

1 つの方法は、インラインで明示的に宣言することです。

inline MyTemplateLibrary::MyTemplateLibrary(){}

または、クラス定義内で定義された関数は暗黙的にインライン化されます。

class MyTemplateLibrary
{
public:
    MyTemplateLibrary() {}

    void function()
    {
        std::cout << "function called!" << std::endl;
    }
};
于 2015-03-23T19:32:50.157 に答える