栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

196-C++重要知识点10

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

196-C++重要知识点10

1.判断下面完全泛化推演的类型是什么?

template
void fun(T a)
{
	T x,y;
	cout << typeid(T).name() << endl;
	cout << typeid(a).name() << endl;
}
int main()
{
	int x = 10;
	const int y = 20;
	int* xp = &x;
	const int* yp = &y;
	fun(x);//T:int a:int
	fun(y);//T:int a:int
	fun(&x);//T:int* a:int*
	fun(&y);//T:const int* a:const int*
	fun(xp);//T:int* a:int*
	fun(yp);//T:const int* a:const int*
	fun(&xp);//T:int** a:int**
	fun(&yp);//T:const int** a:const int**
	return 0;
}

注意:完全泛化中,T和a的类型是一样的

2.判断下面部分特化推演的类型是什么?

template
void fun(T* a)//部分特化
{
	T x = 0,y = 0;
	cout << typeid(T).name() << endl;
	cout << typeid(a).name() << endl;
}
int main()
{
	int x = 10;
	const int y = 20;
	int* xp = &x;
	const int* yp = &y;
	void* p = &x;
	fun(&x);//T:int a:int*
	fun(&y);//T:const int a:const int*
	fun(p);//error
}

注意:部分特化中,T和a不一样,因为void fun(T* a)本身已经给出 * 了,所以a会比T多出一个 *

T x = 0,y = 0;会编译失败,推演之后会变成void* x = 0,y = 0;void* 不能定义类型,所以void* p = &x; fun§;会编译错误,如果把T x = 0,y = 0;去掉,是可以编译通过的

3.判断下面部分特化推演的类型是什么?

template
void fun(const T* a)//部分特化
{
	T x = 0,y = 0;
	cout << typeid(T).name() << endl;
	cout << typeid(a).name() << endl;
}
int main()
{
	const int y = 20;
	fun(&y);//T:int a:const int*
	return 0;
}

注意:部分特化中,void fun(const T* a)已经给出了const和 * ,所以a会比T多出一个cosnt 和 *

4.判断下面引用形式推演的类型是什么?

template
void fun(T &a)//引用
{
	T x,y;
	cout << typeid(T).name() << endl;
	cout << typeid(a).name() << endl;
}
int main()
{
	int x = 10;
	const int y = 20;
	int* xp = &x;
	const int* yp = &y;
	fun(x);//T:int a:int&
	fun(y);//T:const int a:const int&
	fun(xp);//T:int * a:int *&
	fun(yp);//T:const int* a:const int*&
	//fun(&x);//&x:x的地址是一个常量,所以要对引用有const修饰,即int* const &p = &x;但是编译器不能推演出这样,编译器只能在int 和 * 中间推演出const,不能在int* 之外推演出const,所以不能编译通过,如果想让他编译通过,就在void fun(T& a)中加上void fun(T const &a)
	//fun(&y);//T:const int* a:const int*&
	return 0;
}

注意:是可以引用一个指针的

5.模板函数的重载

template
void fun(T a,int)
{}
void fun(T a,char)
{}
int main()
{
	fun(12,23);//调用第一个函数
	fun(12,'a');//调用第二个函数
	return 0;
}

6.类模板和函数模板不同,类模板不存在推演的过程,必须要给出类型Stack st;

template
class Stack
{
private:
	T* data;
	size_t count;
public:
	void Push(const T& x);
};
int main()
{
	Stack st;
}

注意:不是进行替换(即不是用int替换T),而是代码的生成,会编译成下面的程序

class Stack
{
typedef int T;//using T = int   两者是等价的,这是c11的标准
private:
	T* data;
	size_t count;
public:
	void Push(const T& x);
};

7.下面程序is和ist的类型一样吗?

template
class Stack
{
private:
	T data[N];
public:
	void push(const T& x)
};
int main()
{
	Stack is;
	Stack ist;
	return 0;
}

答案:不一样。会在编译时分别生成如下的代码

class Stack
{
typedef int T;
private:
	T data[100];
public:
	void push(const T& x)
};

class Stack
{
typedef int T;
private:
	T data[10];
public:
	void push(const T& x)
};

template中T是类型,N是非类型,N在编译的时候就进行了替换,可以理解为是宏替换

如果类模板中的成员函数没有被调用,那么该成员函数不会被实例化,只有在调用时,才会进行实例化

注意:对于模板来说,模板类和模板的成员函数都包含在一个头文件中,现有的编译器无法做到这一点,即在头文件中进行模板的设计,在.cpp文件中引入头文件,然后实现成员函数,因为依赖关系太复杂了,没有人能做到,所以现有的编译器都不能做到这一点

8.类模板默认值

template
class Stack
{
private:
	T data[N];
public:
	void push(const T& x)
	{
		cout << N << endl;
		N = 100;
	}
};
int main()
{
	Stack st;//编译器可能会编译通过,也可能不会编译通过,最好不用这种方法
	Stack<> st;//yes。告诉编译器是一个是一个模板类型
	Stack ist;//yes
	Stack ist2;//yes
	Stack<,1000> ist3;//error,默认值传参数的时候是从左向右传,不能跳过
}

设置默认值的时候是从右向左,不能跳过,传递参数的时候从左向右传递,也不能跳过

9.多模板参数类型

template
class Queue
{};

当类型更多时,可以用下面的方法

template//c11标准
class Queue
{};

这个叫多模板参数类型

10.模板类型里面可以是类型也可以是非类型

11.对于自定义类型,最好不要用new来开辟连续的空间

template
class Array
{
private:
	enum{ INIT = 10 };
	T* data;
	size_t capacity;//容量
	size_t count;//元素个数
public:
	Array()
	{
		count = 0;
		data = new T[capacity = INIT];
	}
	~Array() {delete[] data;}
};
class String
{
private:
	char* str;
public:
	String(const char*p = NULL) {}
};
int main()
{
	Array sar;
}

这时T就是String类型,new不仅要开辟10个格子的空间,而且还要调用构造函数来实例化对象,但是此时sar.count值为0,这就造成了逻辑上和物理上的冲突,所以对于自定义类型来说,不要使用new来开辟连续的空间,对于内置类型来说,是可以的

12.T是一个模板类型,什么类型都可以,Seq必须是一个模板类型

template class Seq>
int main()
{
	Container iic;//是错误的,第二个int不是模板类型
	Container container;//是正确的,Array是一个模板类型
	Container> container;//是错误的,指明了Array是一个具体类型,处理int类型,就不能编译通过了
}

13.此时Array iar不是模板类型,因为编译器在编译时,它看到int时,会生成代码第二个程序代码,他已经进行实例化了,实例化成Array数组类型来处理整型

template
class Array
{
private:
	enum{ INIT = 10 };
	T* data;
	size_t capacity;//容量
	size_t count;//元素个数
public:
};
int main()
{
	Array iar;
}

class Array
{
	typedef int T;
private:
	enum{ INIT = 10 };
	T* data;
	size_t capacity;//容量
	size_t count;//元素个数
}

当定义Array ;时它是一个模板类型,因为没有加<>,没有表明他是一个什么类型,就算模板有默认值类型template那么它依然是一个模板类型

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/739515.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号