这是我在设计界面时遇到的问题的一个例子。
我有一个动物类,我从中获得了猫,狗和狮子。现在我有一个函数'feedFood',它接受基类Animal作为参数。根据动物的类型,我应该给动物喂食不同的食物。
那么如何在'feedFood'功能中检查动物的类型。
我能想到的方法有三种
哪种方法最好,还是有其他更好的方法?
答案 0 :(得分:6)
你现在这样说:
void feedFood(Animal &);
Cat myCat;
Dog myDog;
feedFood(myCat);
feedFood(myDog);
// Problem: How does feedFood() know what's going on?
要使用多态,请将feed函数设为Animal
:
struct Animal
{
virtual void feedFood() = 0; // pure virtual or default behaviour, up to you
virtual ~Animal() { } // always provide virtual destructor!
/* ... */
};
struct Cat : public Animal
{
void feedFood() { /* Cat implementation */ }
/* ... */
};
// Usage:
// via reference
void feed(Animal & a) { a.feedFood(); }
// via pointer
Animal * b = new Bat;
b->feedFood();
答案 1 :(得分:1)
试试这个:
class Animal{};
class Dog: public Animal{};
class Cat: public Animal{};
class Lion: public Animal{};
void FeedFood(Dog& d)
{
cout << "Feeding the dog.\n";
return;
}
void FeedFood(Cat& c)
{
cout << "Feeding the cat.\n";
return;
}
void FeedFood(Lion& l)
{
cout << "Feeding the lion.\n";
}
void FeedFood(Animal& a)
{
cout << "Feeding an unknown animal.\n";
return;
}
通过上述功能,编译器将负责喂养动物。
有时,功能可能更好地放在课外。
答案 2 :(得分:1)
好的,有点复杂,但在编译时解决:
template <class _Derived>
class Animal
{};
class Dog: public Animal<Dog>
{
public:
void Feed()
{
cout<<"Feeding Dog...";
}
};
class Cat: public Animal<Cat>
{
public:
void Feed() { /* Feed Cat*/ }
};
并实现一个模板功能:
template<class _AnimalType>
void FeedAnimal(_AnimalType& animal)
{
animal.Feed();
}
创建任何类的实例,并调用 FeedAnimal :
Dog dog;
Cat cat;
FeedAnimal(dog);
FeedAnimal(cat);
如果 derived-class 未实现Feed,则在调用Feed模板功能之前,可能不会出现错误。因此,如果Lion实现如下:
class Lion : public Animal<Lion>
{};
您不会收到课程中缺少Feed的任何错误。一旦您使用Lion调用FeedAnimal,您就会收到Lion缺少Feed方法的错误。
这是确保派生类实现Feed的方法之一:
template <class _Derived>
class Animal
{
void (_Derived::*pDummy)();
public:
Animal()
{
pDummy = &_Derived::Feed;
}
};
很脏,但有效!
答案 3 :(得分:0)
不是动物得到了食物,但它吃了它。因此,添加一个虚拟的“吃”方法以及动物可以吃的一些FoodProvider。
<强>更新强>:
所以而不是
void feed (const Food & food);
使用
virtual void eatFrom (FoodProvider * provider);
通过这种方式,您还可以在提供商中实施不同的食物资源。