只学了一点皮毛的cpp,果然我还是更喜欢Java一点
1.关于模板的语法书写
templatetemplate //这两种语法是完全相同的
看似来很像泛型...但是不一样
2.关于方法模板的书写方式
基本语法,在方法声明的上面加上模板声明,在方法的形参列表中就可以使用这种未确定的T类型
templatevoid us(T& a, T& b) { if (a < b) { cout << "jdojj" << endl; } }
函数模板是在底层,根据确定后的数据类型开始生成不同的重载
这里只要注意两个问题即可
(1)在传入的时候,后台会自动识别T是什么,比如传入数字1,2,接下来就会把T类型默认为int
但是注意传入的时候不要出现歧义,如传入(1, 1.2),无法识别T究竟是什么
这种情况下我们一般使用 us
(2)在传入参数或者调用方法的时候要让后台识别出T究竟是什么
举两个例子
templatevoid method1(T t){ }//这个方法,一般在传入参数的时候就可以断定了 template void method2(){ cout< ();//直接手动指明
补充两个
(1)关于函数的模板重载
//经过模板重载的函数 templatevoid us(T& a, T& b) { if (b> a) { cout << "jdojj" << endl; } } //普通函数 void us(int a, int b) { if (b > a) { cout << "jdojj" << endl; } }
一般来说,符合参数规格时优先调用普通函数
否则就是模板函数
如果非要调用模板函数,可以在调用模板函数之前加上一个空泛声明
us<>(1,2); 这样就算传入了明确的int,还是会自动跑到模板函数里面
(2)模板并非万能的
如果是传入自定义类型,并且对自定义类型对象进行操作的话,有一个新方法是这样的
templatevoid us(T a, T b) { if (b > a) { cout << "jdojj" << endl; } } //具体化后的其中一个模板 template<> void us(int a, int b) { if (b> a) { cout << "jdojj" << endl; } }
//我感觉是没啥用,,不如运算符重载(是有效的)或者直接来个普通函数的重载
(2)模板类
别的模板类的东西慢慢整理吧,这里先补充点能用的东西
关于模板类的实现(头文件版本)
先举个例子
//头文件 #includetemplate class person { public: person() { } void f(); }; void sub(); //cpp文件 #include #include "text01.h" int a = 12; void sub() { person x; x.f(); } template void person ::f() { }; //main函数里面的东西 #include #include "text01.h" using namespace std; int main() { person b; b.f(); }
这里再创建的时候会出现一个问题
找不到 person
问题在于,编译顺序是依次独立进行的,一个东西编译完就算一个
在自己编译的过程中,h->cpp过程方法没有调用,没有构建出方法来
h->main的过程中,这个方法只有一个声明,根本就没有构建
所以报错
(不调用就不构建,类模板方法的一个特性)
所以真正调用的时候根本就找不到,所以报错
解决方法有三种
void sub() {
person x;
x.f();
//问题果然杵在这里,因为i这些文件都是分开单独编译的
// 所以那个T最多传到头文件里面,而穿不进这里
// 这里根本没有生成int的模板方法
// 所以这里的T仍然没有分配空间
//解决方法有三个
//1,课件上的解决方法是,像这样写一个方法
//在编译的时候,编译这个sub普通方法的过程中,会提前调用一次,创建一个int的模板
//接下来就可以调用了
//解决方法2:
//2.把方法声明写在头文件里面
//解决方法3:
//直接把这个实现文件也包括进去(太粗叶了这个方法)
}



