首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何处理一个子类有一个方法,而另一个子类没有它?

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

Stack Overflow用户
提问于 2013-12-24 06:15:47
回答 2查看 157关注 0票数 0

我有一个关于界面的问题,比如说:

代码语言:javascript
复制
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();
        ...
    } 
};

现在,我需要这只猫来捕获一只鼠标catchMouse() { std::cout <<“捕捉老鼠”;}

代码语言:javascript
复制
void haveCat()
{ ...
  type = AnimalFactory::animal_type::cat;
  _animal = AnimalFactory.createAnimal(type);
  _animal->makeSound();
  // catchMouse();
  ...
}

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

  1. 在IAnimal中添加一个方法,然后在使用AnimalFactory创建cat之后,我可以从IAnimal调用catchMouse()方法。但catchMouse并不适合所有的动物,狗也不适合catchMouse。在IAnimal中添加一个方法会污染界面、嗅探代码。
  2. 在Cat中添加一个公共方法catchMouse(),并将_animal转换为haveCat()方法中的Cat。 { std::dynamic_pointer_cast(AnimalFactory.createAnimal(type));_ _cat ->make人声();__cat->流域老鼠();} 但是有一个充满活力的演员,不是很好,对吗?
  3. 让猫实现IAnimal接口和另一个关于鼠标的接口,但是AnimalFactory只返回std::shared_ptr,我们不能在IAnimal中调用catchMouse。

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

解决这个问题的好办法是什么?谢谢。

EN

回答 2

Stack Overflow用户

发布于 2013-12-24 06:59:59

我不认为你真的可以从shared_ptr到凯特,是吗?所以在不了解你的代码库的情况下,我编写了一个小测试程序,

代码语言:javascript
复制
#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)作为一个虚拟函数。

票数 0
EN

Stack Overflow用户

发布于 2013-12-24 08:54:14

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

代码语言:javascript
复制
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中如何通过超级接口IUnknown及其QueryInterface方法解决这个问题感兴趣。实现该体系结构的本地版本是可能的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20755842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档