上机五:模板和异常处理程序设计(2 学时)
实验目的
1.了解参数多态性的概念。
2.熟悉函数模板和类模析的设计和使用方法。
3.掌握 C++异常处理方法和异常类的设计。
了解参数多态性的概念。
熟练掌握函数模板和类模析的设计和使用方法。
实验内容
P197:7.9
设计一个考虑异常情况的分数类模板,实现基本分数运算和分数的输出,并编写测试程序进行测试。
测试例题
[例 7.2] 设计一下复数类模板。要求:
(1)复数类模板的成员函数包括加和输出;
(2)成员函数加既可以是两个复数类模板对象相加,也可以是一个复数类模板对象与另一个模板参数作为实部的数值相加;
(3)设计一个测试主函数,要求测试主函数中同时定义实参为 float 的复数类对象和实参为 double 的复数类对象。
// TemplateComplex.h
template <class T>
class Complex{
T real;
T imag;
public:
Complex(T x=0, T y=0);
Complex Add(const Complex x);
Complex Add(const T x);
void show() const;
};
template <class T>
Complex<T>::Complex(T x, T y)
{
real = x;
imag = y;
}
template <class T>
Complex<T> Complex<T>::Add(const Complex<T> x)
{
return Complex<T>(real+x.real, imag+x.imag);
}
template <class T>
Complex<T> Complex<T>::Add(const T x)
{
return Complex<T>(real+x, imag);
}
template <class T>
void Complex<T>::show() const
{
cout<<"real is "<<real;
cout<<" imag is "<<imag<<endl;
}
在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "TemplateComplex.h"
int main(int argc, char* argv[])
{
Complex<float> x(1.1, 1.1), y(2.2, 2.2), z;
Complex<double> u(1.111111, 1.111111), v(2.22222, 2.22222), w;
z = x.Add(y);
cout<<"z is: ";
z.show();
w = u.Add(v);
cout<<"w is: ";
w.show();
return 0;
}
[例 7.3] 设计一个求两个数中较大数的函数模板
//Max.h
template <class T>
T max(T x, T y)
{
return (x>y)? x:y;
}
在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "Max.h"
int main(int argc, char* argv[])
{
int myIntX = 5, myIntY = 8, myIntC;
float myFloatX = 5.6, myFloatY = 8.9, myFloatC;
54
myIntC = max(myIntX, myIntY);
cout<<"myIntC = "<<myIntC<<endl;
myFloatC = max(myFloatX, myFloatY);
cout<<"myFloatC = "<<myFloatC<<endl;
}
//SeqStack.h
class PushOnFull{ //入栈满异常类
int value;
public:
PushOnFull(int x) : value(x){}
int Value(void){ return value; }
};
class PopOnEmpty{};
class SeqStack{
int *data;
int MaxStackSize;
int top;
public:
SeqStack(int n)
{
top = 0;
MaxStackSize = 0;
data = new int[n];
}
~SeqStack(){ delete data; }
void Push(const int item);
int Pop();
};
void SeqStack::Push(const int item)
{
if(top==MaxStackSize)
throw PushOnFull(item);
data[top] = item;
top++;
}
int SeqStack::Pop()
{
if(top == 0) throw PopOnEmpty();
top--;
return data[top];
}
在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "SeqStack.h"
int main(int argc, char* argv[])
{
SeqStack myStack(10);
try{
for(int i=0; i<11; i++)
myStack.Push(i+1);
}
catch(PushOnFull obj){
cout<<"Stack is full"<<endl;
cout<<"the element is: "<<obj.Value()<<endl;
}
try{
for(int i=0; i<11; i++)
cout<<myStack.Pop()<<" ";
}
catch(PopOnEmpty){
cout<<"Stack is empty"<<endl;
}
}
P197:7.9
设计一个考虑异常情况的分数类模板,实现基本分数运算和分数的输出,并编写测试程序进行测试。
class Fract{
public:
int n; //分子
int m; //分母
Fract(int a=0, int b=1):n(a), m(b){}
Fract Add(const Fract x);
Fract Div(const Fract x);
void show() const;
int MaxComm(int a, int b);
};
Fract Fract::Div(const Fract x)
{
57
58
int a = n*x.m;
int b = m*x.n;
if(b == 0)throw 0;
int c = MaxComm(a, b);
return Fract(a/c, b/c);
}
Fract Fract::Add(const Fract x)
{
int a = n*x.m + m*x.n;
int b = m*x.m;
int c = MaxComm(a, b);
return Fract(a/c, b/c);
}
int Fract::MaxComm(int a, int b)//求 a,b 的最大公约数
{
int r=a%b;
while(r!=0)
{
a = b;
b = r;
r = a%b;
}
return(b);
}
void Fract::show() const
{
cout<<n<<"/"<<m<<endl;
}
(3)在主文件中 work5.cpp 中编辑测试代码:
#include <iostream.h>
#include "Fract.h"
int main(int argc, char* argv[])
{
Fract f1(3, 4), f2(7, 16), f3;
try{
59
f1.Div(f3);
}
catch(int){
cout<<"Divided by Zero!"<<endl;
}
f3 = f1.Add(f2);
f3.show();
}
CHATgpt 会怎么来处理?
好的,下面是一个考虑异常情况的分数类模板,并实现了基本分数运算和分数输出的代码:
~~~c++
#include<iostream>
#include<exception>
using namespace std;
//自定义除数为0异常
struct DIVBYZERO: public exception
{
const char* what() const throw()
{
return "Error: Division by zero!\n";
}
};
template<class T>
class Fraction
{
private:
T numerator; // 分子
T denominator; // 分母
public:
// 构造函数
Fraction(T num, T den);
// getter 方法
T getNumerator();
T getDenominator();
// setter 方法
void setNumerator(T num);
void setDenominator(T den);
// 重载"+"
Fraction operator+(Fraction f);
// 重载"-"
Fraction operator-(Fraction f);
// 重载"*"
Fraction operator*(Fraction f);
// 重载"/"
Fraction operator/(Fraction f);
// 输出分数
void print();
};
// 构造函数实现
template<class T>
Fraction<T>::Fraction(T num, T den)
{
if(den == 0) // 如果分母为0则抛出DIVBYZERO异常
throw DIVBYZERO();
numerator = num;
denominator = den;
}
// getter 方法实现
template<class T>
T Fraction<T>::getNumerator()
{
return numerator;
}
template<class T>
T Fraction<T>::getDenominator()
{
return denominator;
}
// setter 方法实现
template<class T>
void Fraction<T>::setNumerator(T num)
{
numerator = num;
}
template<class T>
void Fraction<T>::setDenominator(T den)
{
// 如果分母为0则抛出DIVBYZERO异常
if(den == 0)
throw DIVBYZERO();
else
denominator = den;
}
// 重载"+" 实现
template<class T>
Fraction<T> Fraction<T>::operator+(Fraction f)
{
T num = numerator * f.denominator + f.numerator * denominator;
T den = denominator * f.denominator;
return Fraction(num, den);
}
// 重载"-" 实现
template<class T>
Fraction<T> Fraction<T>::operator-(Fraction f)
{
T num = numerator * f.denominator - f.numerator * denominator;
T den = denominator * f.denominator;
return Fraction(num, den);
}
// 重载"*" 实现
template<class T>
Fraction<T> Fraction<T>::operator*(Fraction f)
{
T num = numerator * f.numerator;
T den = denominator * f.denominator;
return Fraction(num, den);
}
// 重载"/" 实现
template<class T>
Fraction<T> Fraction<T>::operator/(Fraction f)
{
// 如果除数为0则抛出DIVBYZERO异常
if(f.numerator == 0)
throw DIVBYZERO();
T num = numerator * f.denominator;
T den = denominator * f.numerator;
return Fraction(num, den);
}
//输出分数
template<class T>
void Fraction<T>::print()
{
cout << " " << numerator << "/" << denominator << " ";
}
//测试
int main()
{
try
{
Fraction<int> f1(3,8), f2(1,4);
Fraction<int> f3 = f1 + f2;
Fraction<int> f4 = f1 - f2;
Fraction<int> f5 = f1 * f2;
Fraction<int> f6 = f1 / f2;
cout << "f1:"; f1.print(); cout << endl;
cout << "f2:"; f2.print(); cout << endl;
cout << "f1+f2:"; f3.print(); cout << endl;
cout << "f1-f2:"; f4.print(); cout << endl;
cout << "f1*f2:"; f5.print(); cout << endl;
cout << "f1/f2:"; f6.print(); cout << endl;
Fraction<double> f7(3.2, 1.5), f8(0, 4);
Fraction<double> f9 = f7 + f8;
}
catch(DIVBYZERO &e)
{
cout << e.what() <<endl;
}
return 0;
}
~~~`
代码上注释已经比较详细了,主要实现了以下功能:
1. 自定义除数为 0 异常(DIVBYZERO)。
2. 分别用构造函数和 setter 方法对分子和分母进行初始化,并提供 getter 方法获取成员变量值。
3. 实现基本分数运算符重载( + , - , \* , / )。
4. 实现分数的输出功能。
在测试程序中,我们创建了两个不同数据类型的分数类(int 型和 double 型),并对其+、-、\*、/四种运算符进行了使用。同时,也考虑到了除数为 0 时抛出错误处理。