C++基础知识第八天(模板)

cpp软件架构狮 2018-07-22 18:24:46

1.C++的模板(用于实现泛型编程)

1)模板关键字: template或 template T,T1代表数据类型;

2)定义的模板关键字当前行下一个函数或类有用。

3)分为函数模板和类模板;

4)一旦声明了多个类型 T ,不管用或不用,都必须给它指定类型。

2.函数模板的编译机制:(原理)

1)函数模板具有自动推导功能

2)编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。

3)函数模板通过具体的类型产生不同的函数。

3.模板函数与普通函数的区别

1)函数模板不允许自动类型转换,必须严格匹配。

2)普通函数能自动进行类型转换

template
T ptint(T a, T b ){ }
int show(int a,int b){ }
void main(){ 
	int a = 6; 
	char b = 'c'; 
	print(a,b); //"error",两个变量类型必须相同,不允许进行自动转换
	show(a, b); //"YES" “普通函数能自动进行类型转换”
}

4.函数模板和普通函数一起调用规则

1)函数模板可以像普通函数一样被重载

2)如果函数模板与普通函数一样,C++编译器优先调用普通函数。

例如: template

void print(T a, T b ){ }

void print(int a, int b){ }

void main(){ int a = 4; int b = 9; print(a, b); "此时优先调用普通函数"}

3)如果函数模板能产生更好的匹配,则优先调用函数模板。

例如:template

void print(T a, T2 b ){ }

void print(int a, int b){ }

void main(){ int a = 4; char b = 'u'; print(a, b); "此时优先调用函数模板"}

4)可以通过空模板实参列表的语法限定编译器只能调用模板函数

例如:(此目录第二个函数例子)

void main(){ int a = 4; int b = 6; print<>(a, b); }

4.类模板:

1)只能显示的指定类型,不具有自动推导功能。

2)类模板做函数形参(必须显示指定模板类型)

5.类模板与函数模板(有自动推导功能)的混合使用案例,有奇效。

template 
class Person
{
public:
	Person( T1 name, T2 age )
	{
		this->mName	= name;
		this->mAge	= age;
	}
public:
	T1	mName;
	T2	mAge;
};
/* 类模板做函数参数(指定类型) */
void Dobusiness( Person &p1 )
{
	cout << "name:" << p1.mName << " age:" << p1.mAge << endl;
}

/* 类模板与函数模板混合使用(使用函数模板的自动推导功能) */
template 
void Dobusiness02( Person &p1 )
{
	cout << "name:" << p1.mName << " age:" << p1.mAge << endl;
}

void test04()
{
	Person p1( "jonh", 30 );
	Dobusiness( p1 );
	Person p2( "jonheqeq", 303 );
	Dobusiness02( p2 );
}

6.类模板派生普通类和类模板类:

1)继承的话,应该继承一个具体的类,因为一个具体的类,编译器才知道分配多大的内存。

2)如果想继承类模板,应该给继承过程中的类模板显示指定类型。

例如(类模板派生普通类)

template 
class MyClass
{ 
private: //"父类模板"
		T age; };
class SubClass : public Mycalss{ 
	//"普通类,这里继承时,必须对类模板显示指定类型,编译器才知道给父类分配多大的内存"
public:
	int a; };
/* 例如(类模板派生子类模板) */
template 
class MyClass { 
private: //"父类模板"
		T age; };
template 
class SubClass : public Mycalss{ 
	//"子类类模板,这里继承时,可以用子类的类型指定父类的模板"
public:
	T a; };

7.类模板分文件编写

C++文件的编译过程:先每个文件独立编译,然后由链接器将编译好的文件链接在一起(这一步就是寻找各种调用函数,和头文件的定义内容)

需要引入 .cpp 文件,原因:

1)C++编译机制的原因;(分文件编译导致的)

2)二次编译有关

解决办法文件,将他们放入:

类模板的声明与定义要放在一个文件中编写。创建一个.hpp将他们放入

"C++的类型转换"

8.静态类型转换:static_cast<>;

1)用于类层次结构中基类和派生类之间"指针或引用"的转换

1)上行转换:把派生类的指针或引用转换成基类的是安全的 Animal *ani = static_cast( dog ) ;

2)下行转换:把基类的指针或引用转换成派生类的是不安全的,因为没有动态类型检查。 Dog *dog = static_cast(ani);

3)总结一句就是:可以把大的转成小的; 不能把小的转成大的。

2)当两个类之间无继承关系时,不可以进行转换。

如:Teacher *t1 = static_cast(dog); "error,因为两个类之间无关系"

3)基础数据类型之间的转换:

1)可以把高精度的类型转换成低精度的;double da; int a = static_cast(da);

2)当把低

精度的类型转换成高精度时,安全性需要程序员保证。(原理和上一样) double da = static_cast(a);

9.动态类型转换:dynamic_cast<>(类与类之间的转换)

dynamic_cast<> 具有类型检查功能,比 static_cast<>类型转换安全。

1)只能转换具有父子关系的"指针或引用".

上行转换:只能将子类指针转换成父类指针(可以大转小)

下行转换:不能将父类指针转换成子类指针(不能小转大);

例如: parent *parent = dynamic_castson;

10.数组模板:

"1)自定义类型做元素构建数组时,必须提供无参构造函数。"

本页共117段,3029个字符,5662 Byte(字节)