1. 程式人生 > >C++【多型】和【覆蓋】

C++【多型】和【覆蓋】

多型=虛擬函式+指標/引用

關於多型:
形狀:位置,繪製
矩形:寬度、高度,繪製
圓形:半徑,繪製
Shape
/ \
Rect Circle
如果將基類中的某個成員函式宣告為虛擬函式,那麼其子類中與該函式具有相同原型的成員函式就也成為虛擬函式,並對基類中的版本構成覆蓋(override)。通過一個指向子類物件的基類指標,或者引用子類物件的基類引用,呼叫這個虛擬函式時,實際被呼叫的將是子類中的覆蓋版本。這種特性被稱為多型。

關於覆蓋
1.基類中成員函式必須是虛擬函式。
2.子類中成員函式必須與基類中的虛擬函式擁有完全相同的函式名、形參表和常屬性。
3.如果基類中的虛擬函式返回基本型別,那麼子類覆蓋版本的返回型別必須與基類完全相同。如果基類中的虛擬函式返回類型別的指標或者引用,那麼子類覆蓋版本的返回型別可以是基類返回型別的子類。
class X { … };
class Y : public X { … };
class A {
virtual int foo (void) { … }
virtual X* bar (void) { … }
};
class B : public A {
int foo (void) { … }
Y* bar (void) { … }
};
4.子類中的覆蓋版本不能比基類版本丟擲更多的異常。
5.子類中覆蓋版本與基類版本的訪控屬性無關。
class A {
public:
virtual int foo (void) { … }
};
class B : public A {
private
int foo (void) { … }
};
B b;
b.foo (); // ERROR !
A* p = &b;
p -> foo (); // OK !

多型的實現離不開基類與子類之間的覆蓋關係

示例程式碼:

#include <iostream>
using namespace std;
class Shape {
public:
    Shape (int x, int y) : m_x (x), m_y (y) {}
    virtual void draw (void) const = 0;
protected:
    int m_x;
    int m_y;
};
class Rect : public Shape {
public:
    Rect (int x, int y, int w, int h) :
        Shape
(x, y), m_w (w), m_h (h) {} void draw (void) const { cout << "矩形:" << m_x << "," << m_y << "," << m_w << "," << m_h << endl; } private: int m_w; int m_h; }; class Circle : public Shape { public: Circle (int
x, int y, int r) : Shape (x, y), m_r (r) {} void draw (void) const { cout << "圓形:" << m_x << "," << m_y << "," << m_r << endl; } private: int m_r; }; void render (Shape* shapes[]) { for (size_t i = 0; shapes[i]; i++) shapes[i] -> draw (); } int main (void) { size_t i = 0; Shape* shapes[1024] = {NULL}; shapes[i++] = new Rect (1, 2, 3, 4); shapes[i++] = new Rect (5, 6, 7, 8); shapes[i++] = new Circle (9, 10, 11); shapes[i++] = new Circle (12, 13, 14); shapes[i++] = new Rect (15, 16, 17, 18); render (shapes); // Shape shape (0, 0); //virtual 返回型別 函式名 (形參表) = 0; //的虛擬函式稱為純虛擬函式。 //至少含有一個純虛擬函式的類,稱為抽象類。抽象類不能例項化物件。 return 0; }

下面是執行結果:

矩形:1,2,3,4
矩形:5,6,7,8
圓形:9,10,11
圓形:12,13,14
矩形:15,16,17,18