1 / 39

国家级精品课程网站 (本书配套教学网站) programming.xjtu

国家级精品课程网站 (本书配套教学网站) http://programming.xjtu.edu.cn. 第 13 章 模板与异常处理. 13.1 模板 13.2 异常处理机制 13.3 友元 程序设计举例. 13.1 模板. 一、函数模板 1 、定义格式: template << 模板参数表 >> < 类型 > < 函数名 >(< 参数表 >) { … }. 2 、说明

ashlyn
Download Presentation

国家级精品课程网站 (本书配套教学网站) programming.xjtu

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 国家级精品课程网站(本书配套教学网站)http://programming.xjtu.edu.cn国家级精品课程网站(本书配套教学网站)http://programming.xjtu.edu.cn

  2. 第13章 模板与异常处理 • 13.1 模板 • 13.2 异常处理机制 • 13.3 友元 • 程序设计举例

  3. 13.1 模板 • 一、函数模板 • 1、定义格式: • template <<模板参数表>> • <类型> <函数名>(<参数表>) • { • … • }

  4. 2、说明 • (1)<模板参数表>中的模板参数的形式为class <类型参数>,这里关键字class与一般所讲的类无关,而是与<类型参数>一起说明这是一个内部类型或用户自己定义的数据类型。 • (2)在使用模板函数时,模板中的类型参数可用一个实际类型替换,从而达到了类型通用的目的。 • (3)当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数。

  5. [例12-1]求两个数最大值的函数模板 • #include <iostream> • #include <string> • using namespace std; • template <class T> • T Max(T a, T b) • { • return a>b?a:b; • }

  6. // 测试用主函数 • int main() • { • int i1 = 3, i2 = 5; • double d1 = 3.3, d2 = 5.2; • string str1("xjtu"), str2("xian"); • cout << "Type int: " << Max(i1, i2) << endl; • cout << "Type double: " << Max(d1, d2) << endl; • cout << "Type string: " << Max(str1, str2) << endl; • return 0; • }

  7. 3、使用函数模板的注意事项 • (1)在函数模板的参数表中,至少有一个参数的类型为模板的类型参数。另外,函数的返回值的类型也可以是该类型参数。 • (2)模板中可以带有多个参数类型。 • 例如: • template <class T1, class T2, class T3> • void func1(T1 arg1,T2 arg2, T3 arg3) • { • … • }

  8. (3)函数可以带有模板参数表中未给出的、已存在的数据类型的参数。(3)函数可以带有模板参数表中未给出的、已存在的数据类型的参数。 • 例如: • template <class T> • T func2(T arg1,int arg2) • { • … • }

  9. 二、类模板 • 1、类是对问题空间的抽象,而类模板则是对类的抽象,即更高层次上的抽象。 • 2、程序中可以首先定义一个类模板,然后通过使用不同的实参生成不同的类。 • 3、类模板的定义格式: • template <class <类型参数>> • class <类名> • { • …… • };

  10. 例13-2定义一个任意类类型AnyType • #include <iostream> • using namespace std; • template <class T> • class AnyType • { T x, y; • public: • AnyType(T a, T b): x(a), y(b){} • T GetX(){return x;} • T GetY(){return y;} • };

  11. // 测试用主函数 • int main() • { AnyType <int> i (1, 2); • AnyType <double> d (1.5, 2.7); • AnyType <char> c ('a', 'b'); • AnyType <char *> s ("Hello", "template class"); • cout << "整型类:" << i.GetX() << ", " << i.GetY() << endl; • cout << "双精度类:" << d.GetX() << ", " << d.GetY() << endl; • cout << "字符类:" << c.GetX() << ", " << c.GetY() << endl; • cout << "字符串类:" << s.GetX() << ", " << s.GetY() << endl; • return 0; • }

  12. 13.2 异常处理机制 • 异常处理机制的作用: • 使程序可以向更高的层次传递意想不到的事件 • 使程序能更好地从异常事件中恢复过来。 • 异常处理由三个语句实现 • 1. 异常处理的语句 • (1) throw • 用来检测是否产生异常,若是,则抛掷异常。 • 格式: throw 表达式;

  13. (2) try • 是一个复合语句块,它将那些有可能产生异常的语句框定在try块中,并根据异常的情况使用不同的throw表达式抛出异常。 • try { //复合语句 • …… • throw 表达式1; • …… • throw 表达式n; • }

  14. (3)catch • catch块中放置异常处理的语句 • 每个catch块是一个复合语句,处理相应的异常。 • 格式: • catch(异常类型说明1) • { ......//复合语句 • }

  15. 例13-3: 使用异常处理机制 • 使用异常处理机制,检查小学生年龄是否正确,要求能够处理年龄小于0岁和大于20岁的异常情况。 • #include <iostream> • using namespace std; • void testfun(int StudentAge) • {

  16. try • { • if(StudentAge < 0) • throw "输入的学生年龄必须是正整数!"; • if(StudentAge > 20) • throw StudentAge; • cout << "学生年龄是:" << StudentAge <<endl; • }

  17. catch(int i) • { cout << "发生异常:学生年龄是" << i <<"岁,太大了!" << endl; • } • catch(const char* Message) • { cout << "发生异常:" << Message <<endl; • } • }

  18. int main() • { • testfun(12); // 年龄12岁,未发生异常 • testfun(-9); // 年龄-9岁,发生异常 • testfun(77); // 年龄是77岁,发生异常 • return 0; • }

  19. 13.3 友元 • 允许类外部的函数或者类具有该类私有成员的特权。 • 一、友元函数 • 一个类的友元函数是在该类中说明的、用关键字friend修饰的函数,该函数有权访问类中所有的成员。 • 说明一个友元的一般形式为 • friend <类型> <函数名>(<参数表>);

  20. 例如: • class Person • { ...... • public: • friend void FriFunc(Person& person); • ... ... • }; • void FriFunc(Person &person) • { ...... • } • 一个类的友元可以是类外的任何函数,包括不属于任何类的函数和属于某个类的成员函数。

  21. 二、友元类 • 当一个类成为另一个类的友元时,就构成了友元类。这意味着该类的每一个成员函数都是另一个类的友元函数。如: • class Person • { • ...... • public: • friend class Government; • ... ... • };

  22. 程序设计举例 • 定义一个求指数为正整数的幂函数的函数模板,并测试之。 • // Example 13-4:指数为正整数的幂函数模板 • #include <iostream> • using namespace std; • template <class T> • T Power(T a, int exp) • { • T ans = a; • while(--exp>0) ans*=a; • return ans; • }

  23. // 测试用主函数 • int main() • { • cout << "3^5= " <<Power(3, 5) << endl; • cout << "1.1^2= " << Power(1.1, 2) << endl; • return 0; • }

  24. 例 13-5: 顺序查找算法 • #include <iostream> • using namespace std; • template <class T> • int sequentialsearch(T a[], const T& k, int n) • { • int i=0; • while(k!=a[i]&&i<=n-1) • i++; • if(i>n-1)i=-1; • return i; • }

  25. // 测试用主函数 • int main() • { • int i1[] ={3, 2, 5, 0, -1, 7}; • double d1[] ={3.3, 2.1, 0.3, 1.5, 10.6, 5.2}; • char *c1="xjtu"; • cout <<sequentialsearch(i1, 15, 6)<< endl; • cout <<sequentialsearch(d1, 3.3, 5)<< endl; • cout <<sequentialsearch(c1, 'j', 4)<< endl; • return 0; • }

  26. 例13-6:通用的栈类 • #include <iostream> • using namespace std; • template <class T, int n = 10> • class AnyStack • { T m_tStack[n]; • int m_nMaxElement; • int m_nTop; • public: AnyStack() : m_nMaxElement(n), m_nTop(0){} • int GetTop() {return m_nTop;} • bool Push(T); //入栈函数 • bool Pop(T&); //出栈函数 • };

  27. template <class T, int n> • bool AnyStack <T, n>::Push(T elem) • { • if(m_nTop<=m_nMaxElement) • { • m_tStack[m_nTop] = elem; • m_nTop++; • return true; • } • else • return false; • }

  28. template <class T, int n> • bool AnyStack <T, n>::Pop(T &elem) • { • if(m_nTop > 0) • { • m_nTop--; • elem = m_tStack[m_nTop]; • return true; • } • else • return false; • }

  29. // 测试用主函数 • int main() • { • int n; • char * s1; • AnyStack <int> iStack; //定义一个整数栈 • iStack.Push(5); • iStack.Push(6); • iStack.Pop(n); • cout << "第一个出栈整数= " << n << endl; • iStack.Pop(n);

  30. cout << "第二个出栈整数= " << n << endl; • AnyStack <char *> strStack; //定义一个字符串栈 • strStack.Push("It's first string"); • strStack.Push("It's second string"); • strStack.Pop(s1); • cout << "第一个出栈字符串=" << s1 << endl; • strStack.Pop(s1); • cout << "第二个出栈字符串=" << s1 << endl; • return 0; • } • 除0异常。

  31. //Example 13-7: 除0异常 • #include <iostream> • using namespace std; • double Div(double a, double b);

  32. // 测试用主函数 • int main() • { double n1, n2, result; • cout<<"Input two numbers(other characters will terminate the program):"<<endl; • while(cin>>n1>>n2) • { • try • { result=Div(n1,n2); • cout<<n1<<"/"<<n2<<"="<<result<<endl; • }

  33. catch(double) • { • cout<<" Exception occurred: attempted to divide by zero."<<endl; • } • cout<<"Input two numbers(other characters will terminate the program):"<<endl; • } • cout<<"That is ok."<<endl; • return 0; • }

  34. double Div(double a, double b) • { • if(b==0.0) • throw b; • return a/b; • }

  35. 例13-8 解一元二次方程 • 求一元二次方程ax2+bx+c=0的根,其中系数a、b、c均为实数,其数值由键盘输入。要求使用异常处理机制。 • //Example: • #include <iostream> • #include <cmath> • using namespace std; • void Root(double a,double b,double c) • { • double x1, x2, delta; • delta=b*b-4*a*c;

  36. if(a==0) throw "divide by zero"; • if(delta<0) throw 0; • x1=(-b+sqrt(delta))/(2*a); • x2=(-b-sqrt(delta))/(2*a); • cout<<"x1="<<x1<<endl<<"x2="<<x2<<endl; • }

  37. int main( ) • { double a, b, c; • cout << "please input a, b, c = ? "; • cin >> a >> b >> c; • try • { Root(a,b,c); • }

  38. catch(char *) • { cout<<" Exception occurred: it is not a quadratic equation. "<<endl; • } • catch(int) • { cout<<" Exception occurred: the real root of this equation does not exist. "<<endl; • } • return 0; • }

  39. 结 束 语 • 学好计算机的唯一途径是 • 你的编程能力与你在计算机上投入的时间成 上机练习 正比

More Related