检查派生类类型

时间:2011-06-16 19:29:02

标签: c++ derived-class

这是我在设计界面时遇到的问题的一个例子。

我有一个动物类,我从中获得了猫,狗和狮子。现在我有一个函数'feedFood',它接受基类Animal作为参数。根据动物的类型,我应该给动物喂食不同的食物。

那么如何在'feedFood'功能中检查动物的类型。

我能想到的方法有三种

  • 在派生类中设置为正确类型的基类中添加“AnimalType”枚举。
  • 在基类中添加虚函数以返回具有动物类型的字符串。在派生类中,返回动物名称的正确字符串。
  • 使用typeid或dynamic_cast检查'feedFood'函数中派生类的类型。

哪种方法最好,还是有其他更好的方法?

4 个答案:

答案 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);

通过这种方式,您还可以在提供商中实施不同的食物资源。