C/C++教程

196-C++重要知识点10

本文主要是介绍196-C++重要知识点10,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

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

template<class T>
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<class T>
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<class T>
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<class T>
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<class T>
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 T>
class Stack
{
private:
	T* data;
	size_t count;
public:
	void Push(const T& x);
};
int main()
{
	Stack<int> st;
}

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

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

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

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

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

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

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

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

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

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

8.类模板默认值

template<class T = int,int N = 100>
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<int,10> ist;//yes
	Stack<int> ist2;//yes
	Stack<,1000> ist3;//error,默认值传参数的时候是从左向右传,不能跳过
}

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

9.多模板参数类型

template<class T,class U,class R>
class Queue
{};

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

template<class...Arg>//c11标准
class Queue
{};

这个叫多模板参数类型

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

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

template<class T>
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<String> sar;
}

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

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

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

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

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

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

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

这篇关于196-C++重要知识点10的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!