C++ 学习

来源:互联网 发布:cdplay 视频服务器软件 编辑:程序博客网 时间:2024/04/30 05:51
 

内联函数 inline

内联函数的函数体的限制

(1)   函数体不能含有复杂的结构控制语句,如while和switch,若包括的话,编译器将会将其视为普通函数;

(2)   递归不能用于内联函数

(3)   内联函数只适用于小函数

内部函数(static) 外部函数(extern)

 

结构体(struct)和类(class)的差距

默认的访问权限不一致。

       面向对象的三大特点:继承 封装 多态 基于对象

 

类的定义

访问控制:

(1)      用private限定的成员成为私有成员,对私有成员限定在该类的内部使用。类就是私有成员的作用域

(2)      用public限定的成员成为公有成员。对类而言是透明的。

(3)      用protected限定的成员成为公有成员,该类以及该类的派生类中。

 

类中默认的访问权限为private。

 

 

定义类的时候需要注意的几点:
(1)类中的任何数据成员都不可以使用extern  auto register等关键字限定其存储类型

(2)在定义类的时候不能对对类的数据成员进行初始化

类是抽象的,不占用内存,对象是具体的,占用内存。

 

在定义对象的时候,只为每个对象分配用于存储成员数据的存储空间,而成员函数的代码则该类的每一个对象所共享。

 

成员函数的性质:

(1)、与一般函数相比,它的特点和区别

(2)、访问限定

(3)、一般做法

 

同类型的对象之间可以相互整体赋值,这种赋值和对象的成员的访问权限是无关的。

 

一个类的对象可以作为另一个类的成员。

 

类类型的作用域、对象的作用域

 

类是允许嵌套定义的,在定义一个类的时候在,在其类的定义中又包含了一个完整的类的定义。

嵌套类的作用域在外层类的定义结束后结束

 

 

 

成员函数的重载:可以带有缺省的参数,也可重载参数

 

重载的时候必须在形参的类型或者数目上有所不同。(返回值不同算不算,仅有返回值不同是不算的)

成员函数可以有缺省参数,若形参不完全缺省,则必须从形参的右边开始缺省

 

系统会自动将对象的指针带到成员函数中

 

This指针的缺省说明为:类名  const * this

 

构造函数 和析构函数

类的数据成员是不能在定义类的时候进行初始化的

构造函数是在创建对象的时候使用给定的值来将对象初始化。

(1)      可以带参数  可以重载 没有返回值(也不能指定返回值为void)

(2)      构造函数名必须和类名一致

(3)      一个类中可以定义多个类的构造函数

(4)      构造函数可以指定函数的参数的缺省值

(5)      构造函数的访问权限是什么

(6)      所有的对象在定义的时候都必须定义构造函数。

(7)      不存在没有构造函数的对象

(8)      如果定义了没有参数的构造函数或各参数均有缺省值的构造函数,那么这样的构造函数只有一个

(9)      构造对象的顺序(局部对象 全局对象 静态对象)

析构函数是在系统释放对象做善后工作

(1)      在对象对象生命周期结束时,释放系统为对象所分配的空间。

(2)      析构函数不能带有任何参数,不能有返回值,不指定类型

(3)      析构函数不允许重载

(4)      析构函数是在撤销对象的时候由系统自动调用的

(5)      在程序的执行过程中,当遇到某一对象的生命周期结束的时候,系统会自动调用析构函数。然后再回收为对象的分配的内存空间

不同存储类型的对象调用构造函数的以及析构函数:(要分清何时调用构造函数何时调用析构函数)

(1)、对于全局定义的对象

(2)、对于局部定义的对象

(3)、用static定义的局部对象

(4)、使用new运算符动态生成的对象,在产生对象的时候调用构造函数。只有在使用delete运算符来释放对象的时候才调用构造函数。

任何对象都必须有构造函数和析构函数。但在撤销对象的时候,要释放对象的

使用new分配的存储空间的话就必须显示的定义析构函数,在其中使用delete销毁所使用的存储空间

动态构造以及析构对象数组  析构的时候必须delete []对象名

 

 

同种类型的对象之间可以相互赋值,相当英语类中的数据成员之间互相赋值

如果直接将数据赋值给对象,所赋的数据需要强制类型转换,转换的时候需要调用构造函数

当构造函数只有一个参数的时候,可以使用 = 强制赋值

 

C++程序的内存格局通常分为四个区:

(1)      全局数据区 全局变量 静态变量 常量

(2)      代码区

(3)      栈区   局部变量 参数

(4)      堆区

 

类和对象的进一步讨论

 

对于引用类型变量的说明:

(1)、引用在定义的时候就要初始化

(2)、对引用变量的操作就是对被引用变量的操作

(3)、引用类型的变量的初始化不能是一个常数

(4)、引用类型和变量一样有地址,可以对其进行取地址操作

(5)、可以用动态分配的内存空间来初始化一个引用变量

#include <iostream>

 

using namespace std;

 

int main(int argc,char *argv[])

{

       float&ref = * new float;

       ref= 20;

       cout<< ref << endl;

       delete&ref;

       return0;

}

 

指针和引用的区别:

引用在初始化后不能再作为其他变量的别名。

下面三种情况对引用的使用是错误的:

(1)、数组的引用

(2)、指向引用的指针

(3)、引用的引用

 

 

对常量的引用

const int &r = 8 ;//这时r为一个常量

 

 

引用的用途:

(1)、作为函数的参数

#include <iostream>

 

using namespace std;

 

void Change(int &x,int &y)

{

       inttemp ;

       temp= x ;

       x= y;

       y= temp;

}

 

int main(int argc,char *argv[])

{

       int num1 = 3;

       int num2 = 5;

      

       cout << num1 << endl;

       cout << num2 << endl;

 

       Change(num1,num2);

      

       cout <<num1 << endl;

       cout<< num2 << endl;

       return0;

}

 

 

 

Example:

#include <iostream>

 

using namespace std;

//3 4 5

void dd(int &x,int &y, int z)

{//8 -4 5

       x= x + z; //8 4  5          //13 -4  5

       y= y - x; //8 -4 5                 //13-17 5

       z= 10;    //8 -4 10             //13 -17 10

       cout<< x << "\t" << y << "\t" <<z << endl;

}

 

int main(int argc,char *argv[])

{

       inta = 3,b =4,c =5;

       for(inti = 0;i < 2;i++)

       {

              dd(a,b,c);

       }

       cout<<"main  "<< a<< "\t" << b << "\t" << c <<endl;

       return0;

}

 

(2)、作为函数的返回值

使用引用变量作为函数返回值的函数,不能返回自动变量和形参

 

返回变量的引用必须是全局变量或者局部静态静态变量

 

当函数的返回值为引用的时候就可以将这个函数作为左值

 

 

const类型

              拷贝构造函数

完成拷贝功能的构造函数

(1)、在定义一个对象的时候用另一个对象为其初始化,即构造函数的参数是另一个对象的引用。这种构造函数通常为完成拷贝功能的构造函数。

       A::A(A&a)

{

       //函数体

}

 

#include <iostream>

 

using namespace std;

 

class A

{

       floatx,y;

public:

       A(floata = 0,float b = 0)

       {

              cout<< "A(float a = 0,float b = 0) is called"<< endl;

              x= a ;

              y= b;

       }

       A(A&a)

       {

              cout<< "A(A &a) is called"<< endl;

              x= a.x;

              y= a.y;

       }

       voidPrint(void)

       {

              cout<< "void Print() is called "<< endl;

       }

       ~A()

       {

              cout<< "~A() is called "<< endl;

       }

};

 

int main(int argc,char *argv[])

{

       A a1(1.1,2.2);

       A a2(a1);

       a1.Print();

       a2.Print();

       return  0;

}

 

如果没有定义一个完成拷贝功能的构造函数,编译器将会自动生成一个隐含的完成拷贝功能的构造函数,依次完成对类中成员数据的拷贝。

                                      

当类中的成员数据使用了new运算符的时候,就必须显示定义完成拷贝功能的构造函数。

 

浅拷贝 深拷贝

 

 

静态成员

 

当我们将类的一个成员数据的存储类型指定为静态类型的时候,则由该类所产生的所有对象,其静态成员共享一个存储空间,这个存储空间是在编译期间进行分配的,用static关键字进行修饰

对静态成员函数的说明:

(1)、与静态成员数据一样,可以通过类名+ 作用域操作符直接操作静态数据和静态函数

(2)、静态成员函数只能使用本类的静态成员数据或静态成员函数,但是不能直接使用非静态的数据成员,但是可以通过引用使用(它不包含对象地址的this指针)

(3)、静态成员函数的实现部分在类定义之外定义的时候,不能加修饰词static

(4)、不能把静态成员函数定义为虚函数

(5)、可以将静态成员函数声明为内联的。

 

 

 

继承

在C++中所谓“继承”就是在一个已存在的类的基础上建立一个新的类。

在C++语言中,一个派生类可以从一个基类派生,也可以从多个基类派生。从一个基类派生的继承称为单继承;从多个基类派生的继承称为多继承。

 

有三种派生方式:公有派生、保护派生、私有派生。默认的是私有派生。

 

继承的目的:实现代码重用。

派生的目的:当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造。

 

派生的三种方式:

(1)、公有派生  公有派生,派生类中保持基类的成员特性

 

公有派生时,基类中所有成员在派生类中保持各个成员的访问权限

 

基类成员属性

派生类中

派生类外

公有

可以引用

可以引用

保护

可以引用

不可引用

私有

不可引用

不可引用

 

私有派生

私有派生,派生类中基类公有和保护成员成为私有

私有派生时,基类中公有成员和保护成员在派生类中均变为私有的,在派生类中仍可直接使用这些成员,基类中的私有成员,在派生类中不可直接使用。

基类成员属性

派生类

派生类外

公有

可以引用

不可引用

保护

可以引用

不可引用

私有

不可引用

不可引用

 

保护派生

保护派生,派生类中基类公有和保护成员降级使用

保护派生时,基类中公有成员和保护成员在派生类中均变为保护的,在派生类中仍可直接使用这些成员,基类中的私有成员,在派生类中不可直接使用。

基类成员属性

派生类

派生类外

公有

可以引用

不可引用

保护

可以引用

不可引用

私有

不可引用

不可引用

protected 成员是一种具有血缘关系内外有别的成员。它对派生类的对象而言,是公开成员,可以访问,对血缘外部而言,与私有成员一样被隐蔽。

将类的构造函数或析构函数的访问权限定义为保护的时,这种类为抽象类。

 

class  D: public A, protected B, private C

{    ....//派生类中新增加成员

};

这时,可以利用类作用域符::来指明数据或函数的来源。

A::x=a;

        c1.B::Show();

当派生类中新增加的数据或函数与基类中原有的同名时,若不加限制,则优先调用派生类中的成员。

 

 

基类与对象成员

任一基类在派生类中只能继承一次,否则,会造成成员名的冲突

若在派生类中,确实要有二个以上基类的成员,则可用基类的二个对象作为派生类的成员。

 

把一个类作为派生类的基类或把一个类的对象作为一个类的成员,在使用上是有区别的:在派生类中可直接使用基类的成员(访问权限允许的话),但要使用对象成员的成员时,必须在对象名后加上成员运算符“.”和成员名。

 

类的其他特性:

多态性:调用同一个函数名,可以根据需要实现不同的功能

多态性:(1)、函数重载  编译时的多态性

              (2)、虚函数   运行时的多态性

 

在基类和派生类中具有相同的公有函数的情况下,基类对象的指针只能访问从相应基类中继承来的成员,而不允许访问派生类中增加的成员。

若需要指向派生类中的成员函数,则需要将基类中的成员函数声明为虚函数。Virtual

 

若要访问派生类中具有相同名字的函数。必须将基类中的同名函数定义为虚函数。这样将不同的派生类的对象的地址赋值给基类的指针变量后,就可以动态的根据这种赋值语句调用不同类中的成员函数。

 

虚函数的定义和使用

可以再程序运行的时候通过调用相同的函数名而实现不同功能的功能的函数成为虚函数

 

一旦把基类中的成员函数定义为虚函数,由基类中的所派生出来的所有派生类中该函数均保持虚函数的特性。

 

在派生类中重新定义类中的虚函数的时候,可以不用关键字virtual 来修饰这个成员函数。

 

虚函数不能修饰类中的private的成员函数。

它可以在派生类中重新定义,以形成不同的版本,只有在程序执行过程中,依据指针具体指向那个类对象或依据引用那个类对象,才能确定所指向的是哪个版本,实现动态的多态。

 

 

 

关于虚函数需要注意的几点:

(1)、当在基类中把成员函数定义为虚函数后,在其派生类中定义的虚函数必须和基类中的虚函数同名。参数的类型、顺序、个数和函数的返回值类型都必须一致。

(2)、实现这种动态的多态性,必须使用基类类型的指针变量,并使该指针指向不同的派生类对象。并通过调用指针所指向的虚函数才能实现动态的多态性。

(3)、虚函数必须是类的一个成员函数,不能是友元函数也不能是静态的成员函数

(4)、在派生类中没有重新定义虚函数的时候,与一般的成员函数一样,当掉用这种派生类对象的虚函数的时候则调用基类中的虚函数

(5)、可以将析构函数定义为虚函数,但是不能把构造函数定义为虚函数。

(6)、虚函数和一般的函数相比,调用时的执行速度要慢一些,为了实现多态性,在每一个派生类中都需要保存相应的虚函数的入口地址表,寒素的调用机制也是简洁的是按的,因此除了一些必须使用虚函数才能使用其功能外,否则通常是不需要去使用虚函数的

(7)、一个函数无论被派生多少次,仍将保持其虚函数的特性,以实现“一个接口,度多种形态”

 

虚函数表的内容是依据类中虚函数的声明次序一一填入函数指针

派生类会继承基类的虚函数表,当我们在派生类中改写虚函数的时候,虚函数表就会受到影响

 

 

纯虚函数

在基类中不对虚函数给出具体的有意义的实现,它只是在派生类中有具体的意义,这时的基类中的虚函数只是一个入口,具体的目的地有不同的派生类中的对象决定。这个虚函数成为虚函数。

 

Virtual intfunc() = 0;

 

 

(1)、在定义纯虚函数的时候,不能定义虚函数的实现部分;

(2)、把函数名赋值为0 ,本质上是将指向函数体的指针赋值为初值0,和定义空函数不同,空函数的函数体为空,即调用该函数的时候不执行任何动作,在没有重新定义这种纯虚函数之前,是不能定义这种函数的。

(3)、把至少包含一个纯虚函数的类成为抽象类,这种类只能作为派生类的基类,不能用来说明基类的对象。

抽象类的唯一用途是为派生类提供基类,纯虚函数的作用是作为派生类中的成员函数为基础,并实现动态的多态

 

 

 

友元函数

类中的私有和保护成员在类外是不能被访问的。

友元函数是一种定义在类外部的普通函数,其特点是能够访问类中私有成员和保护成员。

友元函数需要在类体外进行声明,在前面加上关键字friend

Friend floatvolume(void);

 

友元函数不是成员函数,用法也和普通的函数一致,只不过它能访问类中所有的数据,友元函数破坏了类的封装性和隐蔽性,使得非成员函数可以访问类中的私有和保护成员。

一个类的友元函数可以自由的使用该类中的所有成员。

#include<iostream>

 

using namespacestd;

 

class A

{

private:

       float x,y;

public:

       A(float a,float b)

       {

              x = a;

              y = b;

       }

       float sum()

       {

              return x + y;

       }

       friend float sum(A &a)

       {

              return a.x + a.y;

       }

};

 

int main(intargc,char*argv[] )

{

       A a1(4,5),a2(10,20);

       cout << a1.sum() << endl;

       cout << sum(a2) << endl;

       return 0; 

}

有关友元函数的说明:

(1)、友元函数不是类的成员函数

(2)、友元函数近似于普通函数,它不带有this指针,因此必须将对象名和对象名的引用作为友元函数的参数,才能访问到对象的成员数据和成员函数

 

 

友元函数和普通函数的区别:

(1)、友元函数必须在类中定义说明,其函数的定义可以再类内也可以在类外

(2)、友元函数可以访问类中的所有成员,不受访问权限的限制。而普通函数只能访问public的成员数据和成员函数

 

友元函数的作用域和一般函数的作用域相同

 

通常使用友元函数来取对象中的数据成员的值,而不改变成员数据的值

 

一个类的成员函数作为另一个类的友元函数的时候要先定义友元函数所在的类

 

 

如果在一个派生类中要访问基类中的私有成员,可以把这个派生类声明为基类的友元

 

#include<iostream>

 

using namespacestd;

 

class B;

 

class A

{

private:

       float x,y;

public:

       A(float a,float b)

       {

              x = a;

              y = b;

       }

       void Sum(B &);

};

class B

{

private:

       float m,n;

public:

       B(float a,float b)

       {

              m = a;

              n = b;

       }

       friend void A::Sum(B &);

};

 

void A::Sum(B&b)

{

       x = b.m + b.n;

       y = b.m = b.n;

}

 

int main(intargc,char*argv[] )

{

       return 0; 

}

 

 

运算符重载

运算符重载的目的:使程序员把C++中的运算符定义扩展为运算分量是对象的情况。

 

编译系统中的运算符“+”本身是不能进行字符串间的”+”操作的,若要实现这种功能,必须重新定义“+”运算符,这中重新定义的过程中成为运算符的重载

 

运算符重载就是赋予已有的运算符多重含义。

 

运算符重载函数通常是类的成员函数或者是友元函数,运算符重载函数的操作数通常是类的对象

A operator()+(A &)

 

operator和 其后的+ 共同构成了函数名。

通过成员函数实现加法运算

#include<iostream>

 

using namespacestd;

 

class A

{

private:

       int i;

public:

       A(int a = 0)

       {

              i = a;

       }

       void Show(void)

       {

              cout <<"i = "<< i << endl;

       }

       void AddA(A &a1,A&a2)

       {

              i = a1.i + a2.i;

       }

};

 

int main(intargc,char*argv[] )

{

       A a1(10),a2(20),a3;

       a1.Show();

       a2.Show();

       a3.AddA(a1,a2);

       a3.Show();

       return 0; 

}

 

通过重载加法运算符实现加法运算

 

#include<iostream>

 

using namespacestd;

 

class A

{

private:

       int i;

public:

       A(int a = 0)

       {

              i = a;

       }

       void Show(void)

       {

              cout <<"i = "<< i << endl;

       }

       void AddA(A &a1,A&a2)

       {

              i = a1.i + a2.i;

       }

       A operator+(A &a)

       {

              A t;

              t.i = i + a.i;

              return t;

       }

};

 

int main(intargc,char*argv[] )

{

       A a1(10),a2(20),a3;

       a1.Show();

       a2.Show();

       a3 = a1 + a2;

       a3.Show();

       return 0; 

}

 

重新定义运算符的时候,由左操作符调用右操作符,最后将函数的返回值赋值给运算结果的对象。

当由左操作符调用右操作符的时候,没有返回值,所以函数的返回值类型为void

 

当用成员函数实现运算符的重载时候,运算符重载的参数只有两种情况:

(1)、没有参数;(只有一个操作数的运算符)

(2)、只有一个参数(有2个操作数的运算符)其中这个参数可以使对象,对象的引用或者其他类型的参数

 

在C++中,不允许重载有三个操作数的运算符

 

C++ 不能重载的运算符有:  .    :: ?: 三种

 

只能对C++中已经定义的运算符进行重载,当重载一个运算符的时候,呀它的它的优先级和结合律师不变的

 

 

 

单目运算符的重载(++ --)

(1)、++ 为前置运算的时候, b = ++ a

A operator ++ ()   {    }

(2)、++ 为后置运算的时候, b = a++

A operator ++ (int)   {    }

 

 

#include<iostream>

 

using namespacestd;

 

class A

{

private:

       int x,y;

public:

       A(float a = 0,float b = 0)

       {

              x = a;

              y = b;

       }

       A operator++()

       {

              cout << "A operator++()is called"<< endl;

              A t;

              t.x = ++x;

              t.y = ++y;

              return t;

       }

       A operator++(int)

       {

              cout << "Aoperator++(int) is called"<< endl;

              A t;

              t.x= x ++;

              t.y= y ++;

              return t;

       }

};

 

int main(intargc,char*argv[] )

{

       Aa(2,3),b;

       b =++a;

       b =a++;

       return0; 

}

 

用成员函数实现运算符的重载时,运算符的左操作符为当前对象。并且隐含用到this,运算符重载函数不能定义为静态的,因为静态的成员函数中是不含有this的

 

 

将运算符的重载函数定义为友元函数的时候,参与运算的对象全部为函数参数。

 

 

 

 

COM的基础学习:

 

COM即组件对象模型,是Component Object Model 取前三个字母的缩写,这三个字母在当今Windows世界中随处可见。随时涌现出来的大把大把的新技术都以COM为基础。各种文档中也充斥着诸如COM对象、接口、服务器之类的术语。因此,对于一个程序员来说,不仅要掌握使用COM的方法,而且还要彻底熟悉COM的所有一切。

 

把一个庞大的软件系统分成多个模块,每一个模块保持功能的独立性,在协同工作时,通过相互之间的接口完成实际的任务,我们把每一个这样的模块称为组件。

 

组件化程序设计不同于传统的面向过程,也不同于现在广泛采用的面向对象技术,它位于两者之上

       组件与组件之间的接口是组件软件的关键,是双方进行通信的基础,接口的设计一定要遵循某种标准,这样才能保证组件之间有共同语言,COM就是大家一致推崇的组件标准。

COM提供接口标准,同时也引入了面向对象思想,对象作为一个元素,在这里我们称之为COM对象,组件模块为COM对象提供了活动空间,对象以接口的形式提供服务。

        在 COM 标准中,一个组件程序也被称为一个模块,它可以是一个动态链接库,被称为进程内组件(in-process component);也可以是一个可执行程序(即 EXE 程序),被称作进程外组件(out-of-processcomponent)。一个组件程序可以包含一个或多个组件对象,因为 COM 是以对象为基本单元的模型,所以在程序与程序之间进行通信时,通信的双方应该是组件对象(COM 对象),而组件程序(COM 程序)是提供 COM 对象的代码载体。

COM 对象不同于一般面向对象语言(如 C++ 语言)中的对象概念,COM 对象是建立在二进制可执行代码级的基础上,而 C++ 等语言中的对象是建立在源代码级基础上的,因此 COM 对象是语言无关的。这一特性使用不同编程语言开发的组件对象进行交互成为可能。

COM接口是COM规范中最重要的部分,COM规范的核心内容就是对接口的定义,甚至可以说“在COM中接口就是一切”。组件与组件之间、组件与客户之间都要通过接口进行交互。接口成员函数将负责为客户或其他组件提供服务。

可以将一个单独的复杂程序划分为多个独立的模块进行开发,这里的每一个独立模块都是一个自给自足的组件,可以采取不同的开发语言去设计每一个组件。在运行时将这些组件通过接口组装起来以形成所需要的应用程序。构成应用程序的每一个组件都可以在不影响其他组件的前提下被升级。这里所说的组件是特指在二进制级别上进行集成和重用而能够被独立生产获得和配置的软件单元。COM规范所描述的即是如何编写组件,遵循COM标准的任何一个组件都是可以被用来组合成应用程序的。至于对组件采取的是何种编程语言则是无关紧要的,可以自由选取。

在 COM 模型中,对象本身对于客户来说是不可见的,客户请求服务时,只能通过接口进行。每一个接口都由一个 128 位的全局唯一标识符(GUID,Global Unique Identifier)来标识。客户通过 GUID 来获得接口的指针,再通过接口指针,客户就可以调用其相应的成员函数。

 与接口类似,每个组件也用一个 128 位 GUID 来标识,称为 CLSID(class identifer,类标识符或类 ID),用 CLSID 标识对象可以保证(概率意义上)在全球范围内的唯一性。实际上,客户成功地创建对象后,它得到的是一个指向对象某个接口的指针,因为 COM 对象至少实现一个接口(没有接口的 COM 对象是没有意义的),所以客户就可以调用该接口提供的所有服务。根据COM 规范,一个 COM 对象如果实现了多个接口,则可以从某个接口得到该对象的任意其他接口。从这个过程我们也可以看出,客户与 COM 对象只通过接口打交道,对象对于客户来说只是一组接口。

 

 

模板和STL介绍

C++中体现重用的两个方面是:

(1)、面向对象的思想:继承 多态 标准类库

(2)、泛型程序设计的思想:模板机制 stl

 

模板的基本概念:

1、 所谓模板就是一种使用无类型参数来产生有一系列函数或者类的机制

2、 若一个程序的功能是对某种特定的数据类型进行处理,则可以将所处理的数据类型说明为参数,以便在其他数据类型的情况下使用,这就是模板的由来

3、 模板是以一种完全通用的方法来设计函数或者类而不必预先说明即将被使用的每个对象的类型

4、 通过模板可以产生类和函数的集合,使它们操作不同的数据类型,从而避免上需要为每一种数据类型产生一个单独的类或者函数

函数模板  类模板

函数模板:独立于类型的函数;可产生函数的特定版本

类模板:跟类相关的模板;可产生类特定类型的版本。

 

模板的工作方式:

1、函数模板只是说明,不能直接执行,需要实例化后的模板函数才能执行

#include <iostream>

 

using namespace std;

template <class T>

T max(T a,T b)

{

       return(a>b)?a:b;

}

 

int main(int argc,char*argv[] )

{

       cout<< max(3,8) << endl;

       return0; 

}

 

#include <iostream>

 

using namespace std;

template <class T>

 

T min(T a[],T n)

{

       inti;

       Tminv = a[0];

       for(i=0;i < n; i ++)

       {

              if(minv> a[i])

              {

                     minv= a[i];

              }

       }

       returnminv;

}

 

int main(int argc,char*argv[] )

{

       intx = 9;

       inta[] = {1,2,3,4,5,6,8,7};

       cout<< min(a,x) << endl;

       return0; 

}

 

模板的缺点:调试困难