大家在使用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ò)嗎?
-
C++
+關(guān)注
關(guān)注
21文章
2085瀏覽量
73302 -
頭文件
+關(guān)注
關(guān)注
0文章
24瀏覽量
9817 -
源文件
+關(guān)注
關(guān)注
0文章
30瀏覽量
4557
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論