原代碼主要問題
- Cone 構造函數調用錯誤:
Cylinder(r), Cylinder(h) 嘗試雙重調用基類構造函數,且參數不匹配
- Sphere 繼承設計缺陷:Sphere 繼承 Circle 但重新定義
radius 導致遮蔽,且 4/3 整除得 1
- Cuboid 未繼承 Shape:導致無法多態使用,且方法內使用未聲明變量
l、w、h
- Rectangle 未實現所有純虛函數:缺少
volume()、surface() 導致抽象類無法實例化
- 主函數邏輯錯誤:
switch 語句結構錯亂,case 不在 switch 內,cout 連寫語法錯誤
修正後的類層次結構
基類 Shape
class Shape {
public:
virtual double area() = 0;
virtual double volume() = 0;
virtual double surface() = 0;
virtual ~Shape() = default; // 虛析構函數
};
二維形狀
class Circle : public Shape {
protected:
double radius;
public:
Circle(double r) : radius(r) {}
double area() override { return PI * radius * radius; }
double volume() override { return 0; }
double surface() override { return 0; }
};
class Rectangle : public Shape {
protected:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double area() override { return width * height; }
double volume() override { return 0; }
double surface() override { return 0; }
};
三維形狀(組合優於繼承)
// 圓柱:組合圓形底面 + 高度
class Cylinder : public Shape {
Circle base;
double height;
public:
Cylinder(double r, double h) : base(r), height(h) {}
double area() override { return base.area(); } // 底面積
double volume() override { return base.area() * height; }
double surface() override { return 2 * base.area() + 2 * PI * radius * height; }
};
// 球體:獨立實現
class Sphere : public Shape {
double radius;
public:
Sphere(double r) : radius(r) {}
double area() override { return 0; } // 球無「面積」概念,或視為表面積
double volume() override { return (4.0/3.0) * PI * radius * radius * radius; }
double surface() override { return 4 * PI * radius * radius; }
};
// 圓錐:組合圓形底面 + 高度
class Cone : public Shape {
Circle base;
double height;
public:
Cone(double r, double h) : base(r), height(h) {}
double area() override { return base.area(); }
double volume() override { return (1.0/3.0) * base.area() * height; }
double surface() override {
double l = sqrt(base.radius * base.radius + height * height); // 斜高
return base.area() + PI * base.radius * l;
}
};
// 長方體:組合矩形底面 + 高度
class Cuboid : public Shape {
Rectangle base;
double height;
public:
Cuboid(double l, double w, double h) : base(l, w), height(h) {}
double area() override { return base.area(); }
double volume() override { return base.area() * height; }
double surface() override {
return 2 * (base.width * base.height + base.width * height + base.height * height);
}
};
主程序邏輯修正
int main() {
while (true) {
cout << "1.圓形 2.長方形 3.長方體 4.圓柱 5.圓錐 6.球體 0.退出\n";
int choice; cin >> choice;
if (choice == 0) break;
Shape* shape = nullptr;
double r, h, w, l;
switch (choice) {
case 1:
cout << "半徑: "; cin >> r;
shape = new Circle(r);
cout << "面積: " << shape->area() << endl;
break;
case 2:
cout << "寬 高: "; cin >> w >> h;
shape = new Rectangle(w, h);
cout << "面積: " << shape->area() << endl;
break;
case 3:
cout << "長 寬 高: "; cin >> l >> w >> h;
shape = new Cuboid(l, w, h);
cout << "表面積: " << shape->surface() << " 體積: " << shape->volume() << endl;
break;
case 4:
cout << "半徑 高: "; cin >> r >> h;
shape = new Cylinder(r, h);
cout << "表面積: " << shape->surface() << " 體積: " << shape->volume() << endl;
break;
case 5:
cout << "半徑 高: "; cin >> r >> h;
shape = new Cone(r, h);
cout << "表面積: " << shape->surface() << " 體積: " << shape->volume() << endl;
break;
case 6:
cout << "半徑: "; cin >> r;
shape = new Sphere(r);
cout << "表面積: " << shape->surface() << " 體積: " << shape->volume() << endl;
break;
default:
cout << "無效選項\n";
continue;
}
delete shape; // 釋放內存
system("pause");
system("cls");
}
return 0;
}
設計原則總結
- 組合優於繼承:三維形狀組合二維底面,而非繼承(球不是圓,圓柱不是圓)
- 虛析構函數:基類析構函數必須聲明為
virtual
- override 關鍵字:C++11 明確標記重寫,編譯器檢查簽名一致性
- 浮點數除法:
4.0/3.0 而非 4/3(整除)
- RAII 原則:動態分配對象需配對
delete,或使用智能指針 unique_ptr