如何处理一个子类有一个方法,而另一个子类没有它?

时间:2013-12-24 06:15:47

标签: c++ inheritance interface subclass factory

我对Interface有疑问,让我们说:

class IAnimal
{ ...
Public:
    virtual void makeSound() = 0;
};

class Cat : public IAnimal
{  ...
    void makeSound() { std::cout << "purr" << std::endl; }
};
class Dog : public IAnimal
{  ...
    void makeSound() { std::cout << "bark" << std::endl; }
};
class AnimalFactory
{
    std::shared_ptr<IAnimal> createAnimal(animalType type)
    {  
        std::shared_ptr<IAnimal> animal;
        switch(type)
        { case animal_type::cat: animal = std::shared_ptr<Cat>(); break; 
          case animal_type::dog: animal = std::shared_ptr<Dog>(); break; 
        … }
        return animal;
    }
};

class App
{ ...
    std::shared_ptr<IAnimal> _animal;
    AnimalFactory::animal_type type;
    void haveCat()
    { ...
        type = AnimalFactory::animal_type::cat;
        _animal = AnimalFactory.createAnimal(type);
        _animal->makeSound();
        ...
    } 
};

现在,我需要这只猫抓老鼠     void catchMouse()     {std :: cout&lt;&lt; “抓老鼠”; }

void haveCat()
{ ...
  type = AnimalFactory::animal_type::cat;
  _animal = AnimalFactory.createAnimal(type);
  _animal->makeSound();
  // catchMouse();
  ...
}

有几种可能的解决方案,但看起来都不好。

  1. 在IAnimal中添加一个方法,然后在使用AnimalFactory创建一个cat后,我可以从IAnimal调用catchMouse()方法。 但是catchMouse不是适合所有动物,狗不会捕捉鼠标。在IAnimal中添加一个方法会污染接口,闻到代码。
  2. 在Cat中添加一个公共方法catchMouse(),并在hasCat()方法中将_animal转换为Cat。

    {
    _cat = std::dynamic_pointer_cast<Cat>(AnimalFactory.createAnimal(type));
    _cat->makeSound();
    _cat->catchMouse();
    }
    

    但是有一个动态演员,不好,对吗?

  3. 让Cat实现IAnimal接口,另一个关于Mouse的接口,但AnimalFactory只返回std :: shared_ptr, 我们不能在IAnimal中调用catchMouse。

  4. 我在这里说的是,在一个子类中有一个公共方法,但是如果我们使用工厂,则另一个子类没有,如何设计它。 请不要回复,让狗抓兔子,然后在IAnimal中添加一个catch()方法,这样,猫可以抓老鼠,狗可以抓兔子。

    这个问题的好方法是什么?感谢。

2 个答案:

答案 0 :(得分:0)

我不认为你实际上可以从shared_ptr转换为Cat,是吗?因此,在不了解您的代码库的情况下,我编写了一个小型测试程序,

#include <memory>
#include <string>
#include <iostream>

class IAnimal
{ 
public:
   virtual void makeSound(){}
};

class Cat : public IAnimal
{  
public:
    virtual void makeSound() { std::cout << "purr" << std::endl; }
    void catchMice(void){
        std::cout<<"mouse catched\n";
    }
};
class Dog : public IAnimal
{  
    virtual void makeSound() { std::cout << "bark" << std::endl; }
};

int main(int argc,char** argv){
    Cat* c = new Cat;
    std::shared_ptr<IAnimal> s(c);
    //you've basically got something of this sort don't you?
    s->makeSound();
    (static_cast<Cat*>(s.get()))->catchMice();
    return 0;
}

应该做你想做的事。我想你可能想把makeSound(void)作为一个虚函数。

答案 1 :(得分:0)

我想,处理问题的方法是解决方案的变化2:使用特殊方法catch创建特定的接口ICatcher并执行以下操作:

AnimalFactory::animal_type type = AnimalFactory::animal_type::cat;
std::shared_ptr<IAnimal> animal = myAnimalFactory.createAnimal(type);
(dynamic_cast<ICatcher*>(animal.get()))->catch();

但在这里你应该确保dynamic_cast会成功或者提供额外的检查。

也许,您也会对超级接口COM及其QueryInterface方法在IUnknown中如何解决此问题感兴趣。可以为该架构实现本地版本。