簡體   English   中英

編寫僅標頭的模板庫時出現“多重定義”錯誤

[英]“Multiple definition of” error while writing a header-only template library

我的項目類似於此設置,當我需要使用my_template_library.hmain_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的末尾,里面包括警衛隊。 只要我的模板庫僅被包含一次,此方法就可以很好地工作,但是當它開始被包含更多時,我遇到了一些非常令人困惑的問題。

$ 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

我對發生的事情感到困惑。 我已經將#pragma message添加到my_template_library.h中,以使您對此有所了解,您在此處看到的已在代碼中注釋掉了。 當我取消注釋並運行代碼時,我得到

$ 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. 如何防止這種情況發生?

為什么包括警衛人員沒有幫助?

包含防護可防止同一編譯單元內出現冗余代碼。

您會收到有關聲稱擁有相同函數定義的不同編譯單元的鏈接器錯誤。

如何防止這種情況發生?

您需要使這些非模板成員函數inline以避免違反“ 一個定義規則”

一種方法是顯式聲明它們內聯。

inline MyTemplateLibrary::MyTemplateLibrary(){}

或者,在類定義中定義的函數是隱式內聯的。

class MyTemplateLibrary
{
public:
    MyTemplateLibrary() {}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM