C++设计如下基本几何图形类: 基础类 CShp 和派生类:点(CPt)、线(CLn); 基础类包含如下接口(虚函数): a) 返回图形类型。 b) 保存数据到文件; c) 从文件读取数据; 然后在类点(CPt)、线(CLn)中实现虚函数。 a) 设计聚合类 CShpDB ,包含成员 CShp 的类指针数组及数组个数。 b) 给聚合类 CShpDB 添加类工厂函数。 c) 给聚合类添加保存文件函数 和 读取文件函数。
时间: 2023-06-16 12:03:26 浏览: 219
以下是可能的实现:
```c++
#include <iostream>
#include <fstream>
using namespace std;
enum class ShapeType {
Point,
Line
};
class CShp {
public:
virtual ShapeType GetType() const = 0;
virtual void SaveToFile(ofstream& file) const = 0;
virtual void LoadFromFile(ifstream& file) = 0;
};
class CPt : public CShp {
public:
CPt() : x(0), y(0) {}
CPt(double x_, double y_) : x(x_), y(y_) {}
ShapeType GetType() const override { return ShapeType::Point; }
void SaveToFile(ofstream& file) const override {
file << "Point " << x << " " << y << endl;
}
void LoadFromFile(ifstream& file) override {
file >> x >> y;
}
double x;
double y;
};
class CLn : public CShp {
public:
CLn() : p1(), p2() {}
CLn(const CPt& p1_, const CPt& p2_) : p1(p1_), p2(p2_) {}
ShapeType GetType() const override { return ShapeType::Line; }
void SaveToFile(ofstream& file) const override {
file << "Line " << p1.x << " " << p1.y << " " << p2.x << " " << p2.y << endl;
}
void LoadFromFile(ifstream& file) override {
file >> p1.x >> p1.y >> p2.x >> p2.y;
}
CPt p1;
CPt p2;
};
class CShpDB {
public:
CShpDB() : shapes(nullptr), numShapes(0) {}
CShpDB(int num) : numShapes(num) {
shapes = new CShp*[numShapes];
for (int i = 0; i < numShapes; i++) {
shapes[i] = nullptr;
}
}
~CShpDB() {
for (int i = 0; i < numShapes; i++) {
delete shapes[i];
}
delete[] shapes;
}
void AddShape(CShp* shape) {
for (int i = 0; i < numShapes; i++) {
if (shapes[i] == nullptr) {
shapes[i] = shape;
return;
}
}
// No space left
cerr << "Error: no space left in shape database." << endl;
}
void SaveToFile(const string& filename) const {
ofstream file(filename);
if (!file.is_open()) {
cerr << "Error: failed to open file for writing." << endl;
return;
}
file << numShapes << endl;
for (int i = 0; i < numShapes; i++) {
if (shapes[i] != nullptr) {
shapes[i]->SaveToFile(file);
}
}
file.close();
}
void LoadFromFile(const string& filename) {
ifstream file(filename);
if (!file.is_open()) {
cerr << "Error: failed to open file for reading." << endl;
return;
}
int num;
file >> num;
if (num != numShapes) {
cerr << "Error: shape database size mismatch." << endl;
return;
}
for (int i = 0; i < numShapes; i++) {
if (shapes[i] != nullptr) {
delete shapes[i];
shapes[i] = nullptr;
}
}
for (int i = 0; i < numShapes; i++) {
string typeStr;
file >> typeStr;
if (typeStr == "Point") {
CPt* pt = new CPt();
pt->LoadFromFile(file);
shapes[i] = pt;
} else if (typeStr == "Line") {
CLn* ln = new CLn();
ln->LoadFromFile(file);
shapes[i] = ln;
} else {
cerr << "Error: unknown shape type." << endl;
return;
}
}
file.close();
}
static CShpDB* Create(int num) {
return new CShpDB(num);
}
private:
CShp** shapes;
int numShapes;
};
```
这个实现中,我们首先定义了基本的抽象类 `CShp`,其中包含了三个纯虚函数,分别用于返回图形类型、保存数据到文件和从文件读取数据。然后,我们定义了两个派生类 `CPt` 和 `CLn`,分别表示点和线。在这两个类中,我们实现了基类中的三个纯虚函数,分别根据自己的数据成员将数据保存到文件或从文件读取。注意,我们在 `CPt` 和 `CLn` 的构造函数中初始化了基类的数据成员,这是因为它们都是 `CShp` 的派生类,需要初始化基类的数据成员。
接着,我们定义了聚合类 `CShpDB`,其中包含了一个动态分配的 `CShp` 类指针数组和数组大小,用于存储多个图形。在这个类中,我们实现了添加图形、保存到文件和从文件读取的功能。其中,添加图形就是简单地将指针放到数组中第一个空位。保存到文件时,我们首先将数组大小写入文件,然后遍历数组,对于非空的指针,调用其 `SaveToFile` 函数,将数据保存到文件。从文件读取时,我们先读取数组大小,并检查是否与当前数组大小匹配。如果不匹配,说明文件中的数据不符合当前程序的要求,应该报错。然后,我们遍历数组,对于非空的指针,先删除原有的对象,然后根据读取到的类型字符串创建新的对象,并调用其 `LoadFromFile` 函数从文件中读取数据。
最后,我们实现了一个类工厂函数 `Create`,用于创建 `CShpDB` 对象,并传递数组大小作为参数。这个函数在本例中可能看起来有点多余,但如果我们在多个文件中分别实现了 `CShpDB` 和其他相关类,那么这个函数就可以用来隐藏实现细节,简化客户端代码。
阅读全文