练习:使用抽象图形类计算面积¶
任务描述¶
设计抽象图形基类 Shape、矩形类 Rectangle 和圆形类 Circle。通过 Shape* 指针调用派生类重写的 PrintArea,输出对应图形的面积。
相关知识¶
纯虚函数¶
纯虚函数在基类中只定义接口,不提供可直接使用的功能:
= 0 表示函数是纯虚函数。派生类必须覆盖它,否则派生类仍是抽象类,不能创建对象。
抽象类¶
包含纯虚函数的 Shape 是抽象类,不能直接定义对象:
但可以定义 Shape* 指针并指向 Rectangle、Circle 等具体派生类对象,以统一接口实现多态。
通过基类指针调用派生类实现¶
当 PrintArea 声明为虚函数时,通过基类指针调用会执行实际对象对应的覆盖版本:
Shape* shape = new Rectangle(10.0f, 2.0f);
shape->PrintArea(); // 调用 Rectangle::PrintArea
delete shape;
基类析构函数也应为虚函数,确保通过 Shape* 删除派生对象时能够正确析构。
编程要求¶
- 使用 C++11 标准编写单文件程序。
- 声明抽象基类
Shape,包含:
- 声明
Rectangle : public Shape,私有成员为float width、float height,并实现:
输出格式为 矩形面积 = 数值,面积为 width * height。
- 声明
Circle : public Shape,私有成员为float radius,并实现:
输出格式为 圆形面积 = 数值,面积为 radius * radius * 3.14。
- 在
test中分别通过Shape*创建、调用并删除矩形和圆形对象,捕获输出后使用assert验证结果。
待完成代码¶
#include <cassert>
#include <iostream>
#include <sstream>
class Shape {
public:
// TODO:声明纯虚函数 PrintArea 和虚析构函数
};
class Rectangle : public Shape {
private:
float width;
float height;
public:
// TODO:实现构造函数和 PrintArea
};
class Circle : public Shape {
private:
float radius;
public:
// TODO:实现构造函数和 PrintArea
};
void test() {
Shape* rectangle = new Rectangle(10.0f, 2.0f);
Shape* circle = new Circle(10.0f);
std::ostringstream output;
std::streambuf* oldBuffer = std::cout.rdbuf(output.rdbuf());
rectangle->PrintArea();
circle->PrintArea();
std::cout.rdbuf(oldBuffer);
delete rectangle;
delete circle;
assert(output.str() == "矩形面积 = 20\n圆形面积 = 314\n");
Shape* smallRectangle = new Rectangle(2.0f, 2.0f);
Shape* smallCircle = new Circle(2.0f);
std::ostringstream smallOutput;
oldBuffer = std::cout.rdbuf(smallOutput.rdbuf());
smallRectangle->PrintArea();
smallCircle->PrintArea();
std::cout.rdbuf(oldBuffer);
delete smallRectangle;
delete smallCircle;
assert(smallOutput.str() == "矩形面积 = 4\n圆形面积 = 12.56\n");
}
int main() {
test();
std::cout << "本关测试通过" << std::endl;
return 0;
}
测试说明¶
第一组使用矩形 10 × 2 和半径为 10 的圆,预期输出:
第二组使用矩形 2 × 2 和半径为 2 的圆,预期输出:
原题中的第一组“10 2.5”与预期面积
20、314无法同时成立。本练习将图形尺寸明确为可验证的参数。
开始你的任务吧,祝你成功!