おそらく、配信元の下位クラスでメソッドが宣言されていないような階層は必要ありませんBird
。そうすれば、統一された階層の要点を失うだけです。Bat
Animal
fly()
次のいずれかを実行できます。
class Animal {
virtual bool canFly() { return false; }
virtual void fly() {throw Exception( "Sorry babe, I don't fly"); }
}
とでオーバーライドfly
します。Bird
Bat
fly()
これにより、おそらく望まない犬や猫用のメソッドが実装されることになります。Flyer
したがって、このメソッドを宣言する新しいクラスを作成できます。
class Flyer : public Animal {
virtual void fly() = 0;
}
class Bat : public Flyer {}
class Bird : public Flyer {}
Reptile
これは、のようなより詳細な生物学的分類と矛盾しますMammal
。
もう 1 つのトリックは、 のようなメソッドを提案しmove()
、犬はそれを として実装しrun()
、鳥は として実装しfly()
、すべて統一されたインターフェイスを使用することです。
もう1つは、犬が飛べるかどうかを尋ねるのは有効な質問だと思うので Dog.canFly()
、アニマルの一部としてコードにメソッドを実装する必要があると思います。
これらすべてを考慮して、私はこれに行きます:
// Your base animal
class Animal {
virtual bool canFly() {return false;}
};
// Any animal that could fly, just abstract class
class Flyer {
virtual void fly() = 0;
}
// Ants, flies etc.; real biological hierarchy
class Insect : public Animal {}
class Mammals : public Animals {}
class Birds : public Animals {}
// And now flying bird :
class Bird : public Birds, public Flyer {
virtual bool canFly() {return true; }
virtual void fly() {...}
}
// And flying insect
class Fly : public Insect, public Flyer {
virtual bool canFly() {return true; }
virtual void fly() {...}
}
そして、あなたはそれを行うことができます(この回答に基づいて、これにはポインターを使用する必要があると思います):
if( Collection[i]->canFly()){
Flyer *thisBird = static_cast<Flyer*>(Collection[i]);
}
仮想継承から派生Flyer
させて使用することもできますが、これは「恐ろしいダイヤモンド」と呼ばれ、良い習慣とは見なされませんが、読む価値があります。Animal
コメントでRicibobが指摘したように、Flyer
を指定する必要がありますcanFly()
。これは、簡単な例では次のようになります。
class Flyer {
public:
virtual bool canFly() const {return true;}
virtual void fly() {cout << "Flying" << endl; }
};
Bird b;
cout << "Can fly: " << b.canFly() << endl;
// Error 1 error C2385: ambiguous access of 'canFly'
しかし、クラスとクラスの一部としてFlyer
配信するAnimal
と、次のようになります。Bird
Birds
Flyer
class Animal {
public:
virtual bool canFly() const {return false;}
};
class Flyer : virtual Animal {
public:
virtual bool canFly() const {return true;}
virtual void fly() {cout << "Flying" << endl; }
};
class Bird : virtual public Birds, virtual public Flyer {
};
// Warning 1 warning C4250: 'Bird' : inherits 'Flyer::Flyer::canFly' via dominance
canFly()
を返すようになりまし1
たが、コードが間違っているようです。
この時点で...canFly()
各サブクラス (または大規模なグループ) に対して手動で指定するか、または配信元(たとえば、これは適切ではありませんBirds
) 、または新しいサブクラスを配信することができます。Flyers
Chicken
class FlyingBrids : public Birds, public Flyer /* Flyer not delivered from Animal */ {
virtual bool canFly() const {return true;}
};
から配信されるFlyer
ため、 は依然として重要であることに注意してください。Fly
Insect