多重继承


继承本身就具有复杂性,在设计上并不鼓励,在可以使用其他设计方式替代的场合,例如合成(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;
}

执行结果如下:

小丑鱼 尼莫 游泳
鲨鱼 兰尼 游泳
人类 贾斯汀 林 游泳
潜水艇 黄色一号 潜行
飞鱼 菲尔普斯 游泳
超人穿着 红色 内裤在游泳
飞鱼 菲尔普斯 飞翔
超人穿着 红色 内裤在飞

这是多重继承的一个简单运用:为了不同状态定义的类实例能够多态。因为继承的来源没有状态定义,只有行为规范,才令多重继承时的复杂度不致于一下难以控制。


展开阅读全文