多重繼承


繼承本身就具有複雜性,在設計上並不鼓勵,在可以使用其他設計方式替代的場合,例如合成(composite),往往建議別使用繼承;C++ 可以多重繼承,也就是子類別可以同時繼承多個父類,既然單一繼承已經有複雜性了,可想而知地,多重繼承更會急劇地增加複雜度。

限制複雜度的方式之一,是限制只能繼承一個具有狀態定義的父類,因為狀態本身就是複雜的根源,同時繼承多個具有狀態定義的父類,只會令狀態的管理更複雜。

來看看從〈純虛擬函式(二)〉衍生出來的簡單情境,如果今天老闆突發奇想,想把海洋樂園變為海空樂園,有的東西會游泳,有的東西會飛,有的東西會游也會飛,那麼現有的程式可以應付這個需求嗎?

仔細想想,有的東西會飛,但這些東西的狀態定義不一定是相同的,有了〈純虛擬函式(二)〉的經驗,你使用定義了 Flyer

class Flyer {
public:
    virtual void fly() = 0;
    virtual ~Flyer() = default;
};

Flyer 定義了 fly 方法,程式中想要飛的東西,可以繼承 Flyer,,而有的東西會飛也會遊,例如飛魚,它是一種魚,可以繼承 Fish,而它也可以飛,因此同時繼承了 Flyer

class FlyingFish : public Fish, public Flyer {
public:    
    using Fish::Fish;

    void swim() override {
        cout << "飛魚 " + this->name + " 游泳" << endl; 
    }

    void fly() override {
        cout << "飛魚 " + this->name + " 飛翔" << endl; 
    }
};

在這邊運用了多重繼承,若要繼承多個父類,只要用逗號區隔就好了,接著你想,來個超人吧!

class SuperMan : public Flyer, public Swimmer {
protected:
    string colorOfunderpants;

public:
    SuperMan(string colorOfunderpants) : 
        colorOfunderpants(colorOfunderpants) {}

    string getColorOfunderpants() {
        return this->colorOfunderpants;
    }

    void swim() override {
        cout << "超人穿著 " + this->colorOfunderpants + " 內褲在游泳" << endl; 
    }

    void fly() override {
        cout << "超人穿著 " + this->colorOfunderpants + " 內褲在飛" << endl; 
    }
};

雖然叫超人,不過電影裡的超人往往不是人,就不繼承 Human 了,而是繼承 FlyerSwimmer;接下來,能游的就游,能飛的就飛吧!

...

void doSwim(Swimmer &swimmer) {
    swimmer.swim();
}

void doFly(Flyer &flyer) {
    flyer.fly();
}

int main() { 
    Anemonefish anemonefish("尼莫");
    Shark shark("蘭尼");
    Human human("賈斯汀", "林");
    Submarine submarine("黃色一號");

    FlyingFish flyingFish("菲爾普斯");
    SuperMan superMan("紅色");

    doSwim(anemonefish);
    doSwim(shark);
    doSwim(human);
    doSwim(submarine);

    doSwim(flyingFish);
    doSwim(superMan);

    doFly(flyingFish);
    doFly(superMan);

    return 0;
}

執行結果如下:

小丑魚 尼莫 游泳
鯊魚 蘭尼 游泳
人類 賈斯汀 林 游泳
潛水艇 黃色一號 潛行
飛魚 菲爾普斯 游泳
超人穿著 紅色 內褲在游泳
飛魚 菲爾普斯 飛翔
超人穿著 紅色 內褲在飛

這是多重繼承的一個簡單運用:為了不同狀態定義的類別實例能夠多型。因為繼承的來源沒有狀態定義,只有行為規範,才令多重繼承時的複雜度不致於一下難以控制。