virtual,派生類**覆寫**(同簽名)。通過基類指標/引用調用時發生**動態綁定**(運行期根據對象真實類型決定調用哪個版本)。virtual RetType func() = 0; 無實作,強制派生類實現。
Shape (抽象基類)
/ | \
Point Circle Cylinder
#include <iostream>
#include <cmath>
using namespace std;
// 1. 抽象基類
class Shape {
public:
virtual float area() const { return 0.0f; }
virtual float volume() const { return 0.0f; }
virtual void shapeName() const = 0; // 純虛函數
virtual ~Shape() = default; // 虛解構函數!關鍵
};
// 2. Point:點(無面積、體積)
class Point : public Shape {
float x_, y_;
public:
Point(float x=0, float y=0) : x_(x), y_(y) {}
void setPoint(float x, float y) { x_=x; y_=y; }
float getX() const { return x_; }
float getY() const { return y_; }
void shapeName() const override { cout << "Point: "; }
friend ostream& operator<<(ostream& os, const Point& p) {
return os << '[' << p.x_ << ',' << p.y_ << ']';
}
};
// 3. Circle:繼承 Point(圓心座標複用)
class Circle : public Point {
float r_;
public:
Circle(float x=0, float y=0, float r=0) : Point(x,y), r_(r) {}
void setRadius(float r) { r_=r; }
float getRadius() const { return r_; }
float area() const override { return 3.14159f * r_ * r_; }
void shapeName() const override { cout << "Circle: "; }
friend ostream& operator<<(ostream& os, const Circle& c) {
return os << static_cast(c) << ", r=" << c.r_;
}
};
// 4. Cylinder:繼承 Circle(底面積複用)
class Cylinder : public Circle {
float h_;
public:
Cylinder(float x=0, float y=0, float r=0, float h=0) : Circle(x,y,r), h_(h) {}
void setHeight(float h) { h_=h; }
float area() const override {
return 2*Circle::area() + 2*3.14159f*getRadius()*h_; // 全表面積
}
float volume() const override { return Circle::area() * h_; }
void shapeName() const override { cout << "Cylinder: "; }
friend ostream& operator<<(ostream& os, const Cylinder& cy) {
return os << static_cast(cy) << ", h=" << cy.h_;
}
};
// 5. 主程式演示靜態/動態綁定
int main() {
Point pt(3.2f, 4.5f);
Circle cir(2.4f, 1.2f, 5.6f);
Cylinder cyl(3.5f, 6.4f, 5.2f, 10.5f);
// 靜態綁定:對象類型確定,編譯期決定調用
pt.shapeName(); cout << pt << endl;
cir.shapeName(); cout << cir << endl;
cyl.shapeName(); cout << cyl << endl << endl;
// 動態綁定:基類指標指向不同派生對象
Shape *sp;
sp = &pt; sp->shapeName(); cout << "x=" << pt.getX() << ",y=" << pt.getY()
<< "\narea=" << sp->area() << "\nvolume=" << sp->volume() << "\n\n";
sp = ○ sp->shapeName(); cout << "x=" << cir.getX() << ",y=" << cir.getY()
<< "\narea=" << sp->area() << "\nvolume=" << sp->volume() << "\n\n";
sp = &cyl; sp->shapeName(); cout << "x=" << cyl.getX() << ",y=" << cyl.getY()
<< "\narea=" << sp->area() << "\nvolume=" << sp->volume() << "\n\n";
return 0;
}
Point: [3.2,4.5]
Circle: [2.4,1.2], r=5.6
Cylinder: [3.5,6.4], r=5.2, h=10.5
Point: x=3.2,y=4.5
area=0
volume=0
Circle: x=2.4,y=1.2
area=98.52
volume=0
Cylinder: x=3.5,y=6.4
area=512.60
volume=891.96
關鍵觀察:同一 Shape* 調用 area()/volume(),根據實際對象(Point/Circle/Cylinder)執行不同代碼 —— **多態**核心價值。
area, volume, shapeName),派生類實現**特有行為**。virtual),建議加 override (C++11) 讓編譯器檢查簽名一致。shape->area(),細節下沉到類庫。interfaces/ 目錄,實現類放入 impl/,通過工廠模式創建對象。