105 C++ 模版及其实例化分析

文章详细探讨了C++中函数模板和类模板的实例化过程,强调了模板在有使用时才会生成具体实现,且实例化仅限于实际调用,包括虚函数的处理和多个源文件中模板的链接行为。
摘要由CSDN通过智能技术生成

零,之前关于模版的简单学习版本

31 C++ 模版和泛型-CSDN博客

一,函数模版再次分析

结论:函数模版在有使用的时候就会生成,而这个使用,不一定是在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>;//显示的实例化,知道这个就行了,看到别人这么写,知道意思就可以,一般不这么用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值