Week03测试说明
问题引入:
使用C++语言编写一系列的类来实现形状相关的操作。要点如下:
- 设计一个抽象基类形状(Shape).这个抽象基类有周长、面积、形状类型等纯虚函数。
- 具体形状有三角形(triangle,用三条边长表示)、正方形(square)、长方形(rectangle)、梯形(trapezium,用上底、下底和左右边长表示)、圆形(round)、复合形状(compoundshape)。这些形状都是由Shape派生。
- 复合形状是指由多个形状组成的形状,组成复合形状的形状可以是普通形状,也可以是复合形状
- 一个复合形状的周长、面积都是它的各个子形状的和
文件分布
- 虚基类Shape
class Shape
{
public:
virtual double area() const = 0; //面积,纯虚函数
virtual double perimeter() const = 0; //周长,纯虚函数
};
- 三角形类Triangle
class Triangle :
public Shape
{
public:
Triangle(double a, double b, double c) :side_A(a), side_B(b), side_C(c) {} //构造函数
virtual double area() const; //定义求面积虚函数
virtual double perimeter() const; //定义求周长虚函数
protected:
double side_A, side_B, side_C; //三条边边长
};
- 正方形类Square
class Square :
public Shape
{
public:
Square(double s) :side(s) {} //构造函数
virtual double area() const; //定义虚函数
virtual double perimeter() const; //定义虚函数
protected:
double side;
};
- 长方形类Rectangle
class Rectangle :
public Shape
{
public:
Rectangle(double w, double l) :width(w), length(l) {} //构造函数
virtual double area() const; //定义虚函数
virtual double perimeter() const; //定义虚函数
protected:
double width, length;
};
- 梯形类Trapezium
class Trapezium :
public Shape
{
public:
Trapezium(double t, double b, double l, double r) :top(t), bottom(b), left(l), right(r) {} //构造函数
virtual double area() const; //定义虚函数
virtual double perimeter() const;//定义虚函数
protected:
double top, bottom, left, right; //上底、下底、 左边长 、右边长
};
- 复合图形类Compoundshape
class Compoundshape :
public Shape
{
public:
Compoundshape(int n, Shape* pr[]); //构造函数
~Compoundshape(){} //析构函数
virtual double area() const; //求复合图形的面积
virtual double perimeter() const; //求复合图形的周长
void setm_num(int n); //设置成员变量m_num的值的函数
protected:
int m_num=0; //符合图形中需加入图形个数
Shape* m_ptr[10]; //默认最大加入10个图形
};
主要说明复合图形类Compoundshape的实现与思路:
复合图形类Compoundshape所创建的复合图形对象可由多个形状组成,组成复合形状的形状可以为基础形状(三角形、正方形…),也可以由复合形状组成,由此可见复合形状类不可以如同三角形类、正方形类一样,拥有固定的形状,因而构造函数以及求面积、周长的函数也与这些基本图形不同,因此需要通过指针动态创建对象,但是由于每个对象的“类别”可能不相同,因此便想到了通过指针数组的形式将各种不同的对象地址传入指针数组中,从而将各个对象的面积、周长进行统一的操作。
- 构造函数
Compoundshape::Compoundshape(int n, Shape* pr[])
{
m_num = n;
for (int i = 0; i < m_num; i++) {
m_ptr[i] = pr[i];
}
}
//复合图形类的构造函数通过将外部指针数组的地址与类中的指针数组成员变量进行初始化
//并将复合图形中的子图形的个数传入,初始化成员变量m_num
- 求复合图形面积函数
double Compoundshape::area() const
{
double area = 0.0;
for (int i = 0; i < m_num; i++) {
area = area + m_ptr[i]->area();
}
return area;
}
//通过循环遍历指针数组中存入的各种图形对象,并将所有图形对象的面积相加求和
- 求复合图形周长函数
double Compoundshape::perimeter() const
{
double perimeter = 0.0;
for (int i = 0; i < m_num; i++)
{
perimeter = perimeter + m_ptr[i]->perimeter();
}
return perimeter;
}
//通过循环遍历指针数组中存入的各种图形对象,并将所有图形对象的周长相加求和
主函数
int main()
{ /*测试一*/
cout << "测试一:三角形、正方形、长方形、梯形、圆形对象的构造以及函数的正确输出" << endl;
Triangle triangle(3.0, 4.0, 5.0); //建立Triangle 类对象
cout<<"三边长为3.0,4.0,5.0的三角形-----面积为:"<< triangle.area()<<" 周长为:"<< triangle.perimeter() << endl;
Square square(3.0); //建立Square 类对象 square
cout << "边长为3.0的正方形-----面积为:" << square.area()<<" 周长为:" << square.perimeter() << endl;
Rectangle rectangle(4.5, 8.5); //建立Rectangle 类对象 rectangle
cout << "长为4.5,宽为8.5的长方形-----面积为:" << rectangle.area()<<" 周长为:" << rectangle.perimeter() << endl;
Trapezium trapezium(8.0, 20.0, 10.0, 10.0); //建立 Trapezium 类对象 trapezium
cout << "上底8.0,下底20.0,左边长10.0,右边长10.0的梯形-----面积为:" << trapezium.area()<< " 周长为:" << trapezium.perimeter() << endl;
Round round(12.5); //建立Round 类对象 Round
cout << "半径为12.5的圆形-----面积为:" << round.area()<<" 周长为:" << round.perimeter() << endl;
cout << "-----------------------" << endl;
/*测试二*/
cout << "测试二:复合图形类的测试" << endl;
Triangle triangleTwo(1.0, 1.0, 1.0); //建立第二个Triangle 类对象 triangle1,三边为1.0,1.0,1.0
cout << "构建三边长为1.0,1.0,1.0的三角形-----面积为:" << triangleTwo.area() << " 周长为:" << triangleTwo.perimeter() << endl;
cout << "在复合类中添加上述三角形、正方形、长方形、梯形、圆形,以及第二个三角形triangleTwo" << endl;
Shape* pr[] = { &triangle,&square,&rectangle,&trapezium,&round,&triangleTwo }; //构建指针数组pr
Compoundshape firstCom(6,pr); //构建复合图形对象firstCom
double areas = firstCom.area(); //areas 为复合图形面积
double perimeters = firstCom.perimeter(); //perimeters为复合图形周长
cout << "复合图形面积 = " << areas << " 复合图形周长 = " << perimeters << endl; //输出复合图形面积,复合图形体积
cout << "-----------------------" << endl;
/*测试三*/
cout << "测试三:将测试二中的复合图形firstCom,作为其中一个子图形加入到一个新的复合图形secondCom中" << endl;
cout << "并将在测试一中创建的:三角形triangle、正方形square加入其中" << endl;
Shape* ps[] = { &triangle,&square,&firstCom }; //构建指针数组ps
Compoundshape secondCom(3,ps); //构建复合图形对象secondCom
cout <<"secondCom的面积:"<< secondCom.area() << endl;
cout << "secondCom的周长:" << secondCom.perimeter() << endl;
cout << "-----------------------" << endl;
return 0;
}
运行结果
从中可以看出,使用了三种方法测试:
- 测试一:三角形、正方形、长方形、梯形、圆形对象的构造以及函数的正确输出
- 测试二:复合图形类的测试
- 测试三:将测试二中的复合图形firstCom,作为其中一个子图形加入到一个新的复合图形secondCom中
附:经过vlb内存测试,并无发现内存泄漏问题
本来的打算是在完成作业的同时学习使用设计模式的单例模式对代码进行优化,但是由于时间仓促,并未完成。下面是个人对设计模式单例模式的学习与了解
单例模式创建要求:
- 某个类只能有一个实例(构造器私有化)
- 它必须自行创建这个实例(含有一个改类的静态变量来保存这个唯一的实例)
- 自行向整个系统提供这个实例(直接暴露或者用静态变量的get方法)
分为饿汉式和懒汉式
各有各的优势与缺点,没有了解的太多,后续会继续学习。