一、模板的组织结构
之前对于模板,我们都是写在同一个 . c p p .cpp .cpp文件下,那如果我们将模板分开,单独开一个 . h .h .h和 . c p p .cpp .cpp来创建模板,会发生什么?
首先,我们创建一个 m y c l a s s . h myclass.h myclass.h文件,写入以下代码:
- #ifndef __MYCLASS_H__
- #define __MYCLASS_H__
- #include<iostream>
- template<typename T>
- class MYClass {
- public :
- void func();
- };
- #endif
复制代码 注意这里的代码是防止多次引用头文件
- #ifndef __MYCLASS_H__
- #define __MYCLASS_H__
复制代码 然后我们创建一个 m y c l a s s . c p p myclass.cpp myclass.cpp文件,类外实现一下模板
- template<typename T>
- void MYClass<T>::func() {
- std::cout << "MYClass::func成员函数执行了\n";
- }
复制代码 然后再主函数 m a i n . c p p main.cpp main.cpp内写入:
- #include "myclass.h"
- int main() {
- MYClass<int> myc;
- myc.func();
- return 0;
- }
复制代码 看上去没什么题目,编译器也没有报错,我们运行一下:
显然,这里链接失败了,缘故原由如下:
编译器首先在 m a i n . c p p main.cpp main.cpp中实行实例化出 M Y C l a s s < i n t > MYClass<int> MYClass<int>这个类,由于在当前编译单元找不到 M Y C l a s s MYClass MYClass类模板的实现,编译器不会因此报错,而是假设在别的编译单元已经实例化出了这个类。但是链接的时候发现别的编译单元也没有实例化出这个类,因此就会发生链接错误。
因此,解决方法就是在 m y c l a s s . h myclass.h myclass.h文件中就完成模板的实现,这样在引用头文件的时候就不会由于编译器的忽略而发生链接错误了:
- template<typename T>class MYClass {public: void func() ;};//直接再.h文件内实现template<typename T>
- void MYClass<T>::func() {
- std::cout << "MYClass::func成员函数执行了\n";
- }
复制代码 编译运行:
二、模板的显式实例化、模板声明、代码组织结构
如果多个 . c p p .cpp .cpp文件调用同一个模板,可能会实例化出多个相同的实例模板,我们可以通过对模板的显式实例化和声明来制止多次实例化。
我们加入 c a . h ca.h ca.h,在里面界说一些模板
- #ifndef __CAH__
- #define __CAH__
- #include<iostream>
- template<typename C>
- class A {
- public:
- //成员函数模板
- template<typename T2>
- A(T2 v1, T2 v2);
- template<typename T>
- void myft(T tmpt) {
- std::cout << tmpt << "\n";
- }
-
- C m_ic;
- };
- //类外实现构造函数
- template<typename T>
- template<typename T2>
- A<T>::A(T2 v1,T2 v2) {
- std::cout << v1 << " " << v2 << "\n";
- }
- //定义一个函数模板
- template<typename T>
- void myfunc(T v1, T v2) {
- std::cout << v1 + v2 << "\n";
- }
- #endif
复制代码 这里有构造函数模板和成员函数模板。
然后我们在 t e s t . c p p test.cpp test.cpp和 m a i n . c p p main.cpp main.cpp中调用这些模板:
t e s t . c p p test.cpp test.cpp:
- #include "ca.h"
- void myfunc() {
- A<float>a(1, 2);
- a.myft(3);
- myfunc(1, 2);
- }
复制代码 m a i n . c p p main.cpp main.cpp:
- #include "ca.h"
- int main() {
-
- A<float>a(1, 2);
- A<float>a2(1.1, 2.2);
- a.myft(3);
- myfunc(1, 2);
- return 0;
- }
复制代码 这样我们会实例化出多个 A < f l o a t > A<float> A<float>和 m y f u n c ( ) myfunc() myfunc()函数,那么我们可以通过模板声明和显式实例化来制止:
在 t e s t . c p p test.cpp test.cpp和 m a i n . c p p main.cpp main.cpp进行更改:
加入以上的内容,注意,实例化声明可以有多个,而实例化界说只能有一个,且必须在界说后才气声明。
这样我们实例化出的模板只会有一个,然后通过在链接的时候就会在别的 . c p p .cpp .cpp文件中找到这个界说。
注意的是,这样的显式实例化界说,如 t e m p l a t e A < f l o a t > template A<float> templateA<float>,会将类 A A A中所有的内容都实例化出来,这样也会带来额外的开销。
总之,对于实例化界说和声明有其优秀的一面,也有其欠好的一面,要看现实环境来选择具体的方法。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |