零,之前关于模版的简单学习版本
一,函数模版再次分析
结论:函数模版在有使用的时候就会生成,而这个使用,不一定是在main方法中。
编译器编译时,根据指针func44的调用来确定T 的类型。
如果我们并没有指针func44的调用代码,那么编译器不会为我们产生任何的func44有关的代码,就好像函数模版没有存在过一样。
void funtest44() {
string s1 = "nihao";
string s2 = "ddd";
fun44(s1, s2);
//fun44("niha", "ss");//build error,会将"niha" 和 "ss"看成两个指针,指针不能相加,因此build error
}
void main() {
cout << "1在只有函数模版的时候,不会生成fun44函数的任何具体方法" << endl;
//2.在指定类型是int 调用的时候, 通过dumpbin分析,会发现有int的fun44方法生成 COMDAT; sym= "int __cdecl fun44<int>(int,int)" (??$fun44@H@@YAHHH@Z)
//int ret = fun44<int>(2, 3);
//cout << "ret = " << ret << endl;
//3.如果不指定呢?
//fun44(1.2, 1.3);// COMDAT; sym= "double __cdecl fun44<double>(double,double)" (??$fun44@N@@YANNN@Z)
//4.如果有实现但是在main中没有调用呢? funtest44()中有实现,但是在main方法中并没有调用 funtest44();也会生成方法的具体实现 COMDAT; sym= "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl fun44<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??$fun44@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V01@0@Z)
//5.也就是说:函数模版在有使用的时候就会生成,而这个使用,不移动是在main方法中。
}
二,类模版的实例化分析
类模版 没有使用的时候就不会生成 类模版类实例
1.模版中的枚举类型
如果模版中有枚举,编译器只是会把 Teacher<int>::LIBAI ,这一串看成一个枚举类型。
Teacher<int>::LIBAI lb;//注意 这里加int,Teacher<int>是个真正的类型,Teacher 不是类型。
//如果是类模版中枚举类型,编译器只是会把 Teacher<int>::LIBAI ,这一串看成一个枚举类型。
//类模版的实例化分析
template <class T>
class Teacher {
public:
Teacher() {
cout << "Teacher gouzao" << endl;
}
~Teacher() {
cout << "Teacher xigou" << endl;
}
T t1;
enum LIBAI {
MONDAY,
SUNDAY
};
};
void main() {
cout << "在Teacher没有使用的时候就不会生成 Teacher类实例" << endl;
Teacher<int>::LIBAI lb;//注意 这里加int,Teacher<int>是个真正的类型,Teacher 不是类型。
//如果是类模版中枚举类型,编译器只是会把 Teacher<int>::LIBAI ,这一串看成一个枚举类型。
lb = Teacher<int>::SUNDAY;
}
2.类模版中的静态成员变量
//类模版的实例化分析
template <class T>
class Teacher {
public:
Teacher() {
cout << "Teacher gouzao" << endl;
}
~Teacher() {
cout << "Teacher xigou" << endl;
}
T t1;
enum LIBAI {
MONDAY,
SUNDAY
};
static double m_sti;
};
//给静态变量赋值
//double Teacher<T>::m_sti = 10; 这样不行.因为编译器还不知道 T 是啥。
template <class T> double Teacher<T>::m_sti = 10.98;//因此要这么写,
void main() {
Teacher<int>::m_sti = 23.1;
//如果只是使用静态成员m_sti,也不会生成类实例
}
3.类模版的实例化
void main() {
Teacher<int>* ptea = nullptr;//这种不会生成实例
}
4.成员函数的实例化
如果类实例化了,成员函数会也跟着实例化吗? 不会。
只有真的使用的时候才会实例化。
普通类也是这样的。
//类模版的实例化分析
template <class T>
class Teacher {
public:
Teacher() {
cout << "Teacher gouzao" << endl;
}
~Teacher() {
cout << "Teacher xigou" << endl;
}
T t1;
enum LIBAI {
MONDAY,
SUNDAY
};
static double m_sti;
void testfun() {
cout << "Teacher testfun" << endl;
}
void testfun1() {
cout << "Teacher testfun1" << endl;
}
};
//给静态变量赋值
//double Teacher<T>::m_sti = 10; 这样不行.因为编译器还不知道 T 是啥。
template <class T> double Teacher<T>::m_sti = 10.98;//因此要这么写,
class Teacher1 {
public:
void testfunTeacher1() {
cout << "Teacher1 testfun" << endl;
}
void testfun1Teacher1() {
cout << "Teacher1 testfun1" << endl;
}
};
void main() {
Teacher<int> tea;
Teacher1 tea1;
}
三,多个源文件中使用类模版
在一般使用类模版时,我们会将类模版放在.h中。
有可能多个文件都会使用这个.h文件,生成模版的具体实例类。
也就是说:在多个.obj中都会有具体实例类,假设都是int的具体实例类。
在链接的时候,VS2017只会保留一个int,其他的都会被忽略掉。
1.虚函数的实例化
有虚函数,就会产生虚函数表,
虚函数表中是各个虚函数表的地址。总不能乱写个地址爸吧。
既然需要各个虚函数表的地址,那么必须要实例化每一个虚函数出来,不然真正的地址不知道。
2.显示实例化。
可以在.cpp文件的开头
使用
template class Teacher<int>;//显示的实例化,知道这个就行了,看到别人这么写,知道意思就可以,一般不这么用