0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

模版定義一定要寫(xiě)在頭文件中嗎?

汽車(chē)電子技術(shù) ? 來(lái)源:程序喵大人 ? 作者:程序喵大人 ? 2023-02-21 14:23 ? 次閱讀

大家在使用C++代碼時(shí)或多或少都會(huì)使用到模板,使用模板時(shí)應(yīng)該都是把定義放在了頭文件中,因?yàn)榉旁谠次募卸x會(huì)編譯失敗。

那問(wèn)題來(lái)了,模板中的函數(shù)定義一定要寫(xiě)在頭文件中嗎?

先說(shuō)結(jié)論:不一定要放在頭文件中,定義也可以放在源文件中,但操作起來(lái)還是有點(diǎn)麻煩的。

繼續(xù)往下看看

先看一段正常的模板代碼:

// template.h
#include 


template <typename T>
struct TemplateTest {
    T value;
    void func();
};


template <typename T>
void TemplateTest::func() {
    std::cout << typeid(T).name() << std::endl;
}


// test_template.cc
#include "template.h"


int main() {
    TemplateTest<int> test;
    test.func();
    return 0;
}

這段代碼沒(méi)啥毛病,因?yàn)閷?shí)現(xiàn)放在了頭文件中,也會(huì)正常輸出。

如果我把函數(shù)定義放在源文件中呢,會(huì)怎么樣?

// template.h
#include 


template <typename T>
struct TemplateTest {
    T value;
    void func();
};


// template.cc
template <typename T>
void TemplateTest::func() {
    std::cout << typeid(T).name() << std::endl;
}


// test_template.cc
#include "template.h"


int main() {
    TemplateTest<int> test;
    test.func();
    return 0;
}

嗯,不出意外,編譯報(bào)錯(cuò)了,報(bào)了個(gè)沒(méi)有某個(gè)函數(shù)實(shí)現(xiàn)的error:

/tmp/ccPghOjU.o: In function `main':
test_template.cc:(.text+0x1f): undefined reference to `TemplateTest::func()'
collect2: error: ld returned 1 exit status

為什么沒(méi)有此函數(shù)定義?

先補(bǔ)充個(gè)基礎(chǔ)知識(shí),模板的本質(zhì)。本質(zhì)其實(shí)就是類(lèi)型泛化,可以用一個(gè)T代替多種類(lèi)型,對(duì)于上面的模板,假如有此種使用:

TemplateTest<int> test;

那模板最終可能變成這樣:

struct TemplateTest_int {
    int value;
    void func() {
        std::cout << typeid(int).name() << std::endl;
    }
};

如果有這兩種使用:

TemplateTest test;
TemplateTest<float> test;

那模板最終可能會(huì)變成這樣:

struct TemplateTest_int {
    int value;
    void func() {
        std::cout << typeid(int).name() << std::endl;
    }
};


struct TemplateTest_float {
    float value;
    void func() {
        std::cout << typeid(float).name() << std::endl;
    }
};

模板最終會(huì)展開(kāi)成什么樣,取決于用戶(hù)是怎么使用它的。

那回到上面的問(wèn)題,為什么把定義放在源文件中,編譯就失敗了呢,因?yàn)槊總€(gè)源文件的編譯都是獨(dú)立的,盡管在test_template.cc進(jìn)行了TemplateTesttest的使用,但是在template.cc中卻感知不到,所以也就沒(méi)法定義相關(guān)的實(shí)現(xiàn)。

思路來(lái)了,只需要讓template.cc中感知到T有int類(lèi)型的情況,那編譯應(yīng)該就沒(méi)問(wèn)題。這里有個(gè)語(yǔ)法,叫模板實(shí)例化,像這樣:

template struct TemplateTest<int>;

把這行代碼放在template.cc中:

// template.cc
#include "template.h"


template <typename T>
void TemplateTest::func() {
    std::cout << typeid(T).name() << std::endl;
}


template struct TemplateTest<int>;

整個(gè)代碼的編譯就沒(méi)得問(wèn)題了,通過(guò)這種方式即可以實(shí)現(xiàn)模板函數(shù)聲明與實(shí)現(xiàn)的分離。

這也印證了上面的結(jié)論。

這里我再拋出 幾個(gè)問(wèn)題 ,大家可以討論討論:

  • 模板的使用是否會(huì)導(dǎo)致代碼段體積增大?怎么解決?
  • 模板的函數(shù)定義放在了頭文件中,好多個(gè)源文件都include此頭文件,是否會(huì)導(dǎo)致函數(shù)的multi definition類(lèi)型的鏈接報(bào)錯(cuò)?實(shí)際使用中貌似沒(méi)有報(bào)錯(cuò),為什么?大家有想過(guò)嗎?
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C++
    C++
    +關(guān)注

    關(guān)注

    21

    文章

    2085

    瀏覽量

    73302
  • 頭文件
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    9817
  • 源文件
    +關(guān)注

    關(guān)注

    0

    文章

    30

    瀏覽量

    4557
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Linux下個(gè)實(shí)用的頭文件

    queue.h是Linux、FreeBSD個(gè)頭文件
    發(fā)表于 12-02 11:48 ?791次閱讀

    modelsim中一定要寫(xiě)testbench文件嗎?

    modelsim中一定要寫(xiě)testbench文件嗎?
    發(fā)表于 03-29 10:02

    定義下的“GPIO_”是什么作用,一定要用嗎

    #defineGPIO_KEY P1//獨(dú)立鍵盤(pán)用P1口#defineGPIO_LED P0//led使用P0口我想知道這個(gè)宏定義下的“GPIO_”是什么作用,一定要用嗎?c程序的GPIO_與通訊輸入\輸出的GPIO是同
    發(fā)表于 05-29 12:22

    頭文件定義全局變量的方法

      教大家個(gè)如何在頭文件定義全局變量的方法  通常情況下,都是在C文件
    發(fā)表于 07-04 08:34

    頭文件定義全局變量的方法介紹

      教大家個(gè)如何在頭文件定義全局變量的方法  通常情況下,都是在C文件
    發(fā)表于 07-09 09:25

    教大家個(gè)如何在頭文件定義全局變量的方法

    通常情況下,都是在C文件定義全局變量,在頭文件聲明,但是,如果我們定義的全局變量需要被很多的
    發(fā)表于 12-04 14:55 ?19次下載

    編程引用頭文件的幾種方法及要點(diǎn)

    好的編程習(xí)慣,會(huì)直接影響代碼的質(zhì)量,在嵌入式C/C++,頭文件的引用方式和方法有多種,同時(shí)些細(xì)節(jié)也會(huì)影響你代碼質(zhì)量和編譯效率。 下面就來(lái)說(shuō)說(shuō)與頭文件有關(guān)的知識(shí); 1 引號(hào)“”和尖括
    的頭像 發(fā)表于 03-12 17:30 ?3206次閱讀

    在keil創(chuàng)立個(gè)頭文件

    定義格式#ifndef _LED_H_#define _LED_H_ //跟在后面的_LED_H_只是個(gè)文件名//內(nèi)容#endif用51單片機(jī)舉例注意在頭文件
    發(fā)表于 11-21 14:06 ?1次下載
    在keil<b class='flag-5'>中</b>創(chuàng)立<b class='flag-5'>一</b>個(gè)<b class='flag-5'>頭文件</b>

    keil添加了頭文件仍然報(bào)找不到頭文件的原因

    ,則需要重新將文件夾包含到工程。4)點(diǎn)擊魔術(shù)棒的C/C++,將包含該頭文件的最內(nèi)層文件夾包含進(jìn)去,
    發(fā)表于 11-21 14:21 ?13次下載
    keil添加了<b class='flag-5'>頭文件</b>仍然報(bào)找不到<b class='flag-5'>頭文件</b>的原因

    單片機(jī)-頭文件

    reg52.h頭文件的作用在代碼引用頭文件,其實(shí)際意義是將頭文件的所用內(nèi)容都放到引用頭文件
    發(fā)表于 11-23 17:21 ?17次下載
    單片機(jī)-<b class='flag-5'>頭文件</b>

    MCU_頭文件編寫(xiě)

    頭文件般放些重復(fù)使用的代碼,如:常量、變量、宏等的定義,函數(shù)的聲明。當(dāng)使用#include語(yǔ)句引用頭頭文件時(shí),相當(dāng)于將
    發(fā)表于 12-05 10:36 ?5次下載
    MCU_<b class='flag-5'>頭文件</b>編寫(xiě)

    【筆記】單片機(jī)頭文件的順序會(huì)讓程序報(bào)錯(cuò)?

    頭文件的正確順序主要涉及以下幾個(gè)方面:1.依賴(lài)關(guān)系和聲明順序:在編寫(xiě)單片機(jī)程序時(shí),可能會(huì)有頭文件之間存在依賴(lài)關(guān)系。某些頭文件
    的頭像 發(fā)表于 05-19 09:50 ?1350次閱讀
    【筆記】單片機(jī)<b class='flag-5'>頭文件</b>的順序會(huì)讓程序報(bào)錯(cuò)?

    什么是頭文件?頭文件編寫(xiě)的般格式要求是怎樣?

    本文介紹頭文件定義、編寫(xiě)、保存及引用等方面的內(nèi)容,包括了般的格式要求、例程等。
    的頭像 發(fā)表于 11-08 16:25 ?1431次閱讀
    什么是<b class='flag-5'>頭文件</b>?<b class='flag-5'>頭文件</b>編寫(xiě)的<b class='flag-5'>一</b>般格式要求是怎樣?

    請(qǐng)問(wèn)頭文件能不能定義變量呢?

    最近在編譯個(gè)工程的時(shí)候,突然遇到了變量重復(fù)定義的問(wèn)題,根據(jù)提示打開(kāi)這幾個(gè) C 文件,并沒(méi)有發(fā)現(xiàn)定義變量的地方。后來(lái)再找找,原來(lái)變量
    的頭像 發(fā)表于 04-28 09:33 ?803次閱讀

    可重復(fù)頭文件的固定結(jié)構(gòu)

    年輕人,你可曾記得,在修習(xí)C語(yǔ)言的時(shí)候,見(jiàn)過(guò)這樣的字句:在創(chuàng)建頭文件的時(shí)候,一定要加入保護(hù)宏。
    的頭像 發(fā)表于 08-29 10:23 ?165次閱讀
    可重復(fù)<b class='flag-5'>頭文件</b>的固定結(jié)構(gòu)