《C++ Template 中文版》第140页测试

2 篇文章 0 订阅
1 篇文章 0 订阅
//头文件
#include <iostream>
using namespace std;

template <typename T>
class Safe{
};

template <int N>
class Danger{
public:
	char Block[N];
};

template <typename T, int N>
class Tricky{
public:
	Tricky(){
		cout << "Tricky" << endl;
	}

	virtual ~Tricky(){
		cout << "~Tricky" << endl; 
	}
	 
	void no_body_here(Safe<T> = 3);//编译器解析时,会觉得此处可疑,但编译器会假设该参数“处于最理想的情况”(assume the best)

	void inclass(){
		Danger<N> no_boom_yet;
	}
	
	void error() { Danger<0> boom; }

	void unsafe(T(*p)[N])
	{
		cout << typeid(p).name() << endl;
	}
	
	//VS2013 提示:
	//error LNK2001: 无法解析的外部符号 "public: virtual class Safe<int> __thiscall
	//Tricky<int,0>::suspect(void)" (?suspect@?$Tricky@H$0A@@@UAE?AV?$Safe@H@@XZ)

	//---《C++ Template》解析:
	//作为实例化类模板的结果,虚函数的定义可能被实例化了,但也可能没被实例化,这要依赖于具体的实现。
	//实际上,许多实现都会实例化(虚函数)这个定义,因为“实现虚函数调用机制的内部结构”要求虚函数
	//(的定义)作为链接实体存在
	//PS:我还不理解 O(∩_∩)O~~
	//virtual Safe<T> suspect();  

	//一个类型而已
	struct Nested
	{
	};

#if 0
	//匿名 union,被当做是成员看待,因此实例化模板时,会去实例化此匿名 union
	union {	
		Danger<N> anonymous2;
		int align;
		Safe<T> anonymous;
		//Danger<N> anonymous2;
	};
#endif

	Danger<N> annonymous3;
};

int _tmain(int argc, _TCHAR* argv[])
{
#if 0	//这里的代码和注释都是正确的,只是为了后面的调试才不用这的代码了
	int (*a)[1] = { 0 };

	//Tricky<int, 2> ok1;
	//ok1.unsafe(a);//error C2664: “void Tricky<int,2>::unsafe(T (*)[2])”: 无法将参数 1 从“int (*)[1]”转换为“int (*)[2]”

	Tricky<int, 1> ok;
	ok.unsafe(a);//输出:int (*)[1]  这是啥类型,指向数组的指针?我想是的

#endif

#if 0	//这里的代码和注释都是正确的,只是为了后面的调试才不用这的代码了
	//如果不调用 inclass/error 成员函数,则编译不产生任何提示,如果调用了呢,提示如下:
		//warning C4200: 使用了非标准扩展 : 结构/联合中的零大小数组
		//当 UDT 包含大小为零的数组时,无法生成复制构造函数或副本赋值运算符
		// : 参见对正在编译的类 模板 实例化“Danger<0>”的引用
		// : 编译类 模板 成员函数“void Tricky<int, 0>::inclass(void)”时
		// : 参见对正在编译的函数 模板 实例化“void Tricky<int, 0>::inclass(void)”的引用
		// : 参见对正在编译的类 模板 实例化“Tricky<int, 0>”的引用
	//解析:
	//当只定义 ok2 的时候,只是进行模板实例化声明,而未进行实例化定义(好像这样的实例化就叫延迟实例化吧),就是说,
	//如果成员函数没调用,就不管这个成员函数有没有定义。当调用了成员函数后,就会去定义一个元素个数为0的数组,然后就产生这个提示了

	Tricky<int, 0> ok2;
//	ok2.inclass(); 
//	ok2.error(); 
#endif

#if 0//有问题,没弄懂
	//我这里只借用了类模板的Nested类型,却对匿名 union 的 Danger<N> anonymous2; 提示:warning C4200: 使用了非标准扩展 : 结构/联合中的零大小数组
	//当 UDT 包含大小为零的数组时,无法生成复制构造函数或副本赋值运算符
	//当然 Danger<N> annonymous3; 也有提示
	//解析:
	//这里对模板进行实例化了,实例化模板时,会去查询成员变量的定义,从而给出warning
	Tricky<int, 0>::Nested nest;//不会有构造和析构函数的打印

	//问题:没弄懂啊~~~
	//当把 Tricky 模板中union处的#if 用#if 1时,会产生错误 error C2229: class“Tricky<int,0>”有非法的大小为零的数组(指向annonymous3)
	//而把 Danger<N> anonymous2; 挪到前面去或者用#if 0时,则无error
#endif

	system("pause");
	return 0;
}

Danger<N> annonymous3; 是第三处测试加上去的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值