你有动物收容所。庇护所可以储存可变数量的动物。你把很多动物(狗和猫)放进收容所。
然后你告诉员工随机挑选并给你带几只动物。你不知道他选择了哪种动物。你叫他们说话。有的是“吠”,有的是“喵”。
重要!狗可以取,猫不能。如果你确实知道你已经选择了一只狗,它应该能够立即取(例如,从动物到狗)。
如何实现这种逻辑?(最好没有助推::任何)
下面是一个部分工作的示例:http://ideone.com/kR4788
#include <iostream>
#include <map>
using namespace std;
class Animal {};
class Shelter {
private:
std::map<int, Animal*> animals;
public:
void Add(Animal* animal) {
animals[animals.size()] = animal;
};
Animal* Select(int index) {
return animals[index];
}
};
class Dog: public Animal {
public:
void Speak() { cout << "bark" << endl; }
void Fetch() {}
};
class Cat: public Animal {
public:
void Speak() { cout << "meow" << endl; }
};
Shelter shelter;
int main() {
shelter.Add(new Cat());
shelter.Add(new Dog());
// I'd like to make it work like this
//
// shelter.Select(0)->Speak(); /* meow */
// shelter.Select(1)->Speak(); /* bark */
//
// Like below but without upcasting to given animal
((Cat*) shelter.Select(0))->Speak();
((Dog*) shelter.Select(1))->Speak();
// I know under index 1 is a Dog so it can fetch!
//
// shelter.Select(1)->Fetch(); /* no segfault */
//
// Like below but without upcasting to given animal
((Dog*) shelter.Select(1))->Fetch();
return 0;
}发布于 2014-04-02 10:16:08
根据要求,我把我的评论作为答复。完整的源代码在艾德龙中
在课堂上动物:
class Animal {
public:
virtual void Speak() const = 0;
virtual void Fetch() const { cout << "This animal can't fetch" << endl;};
virtual ~Animal(){ }
};需要虚拟析构函数来确保为从基类派生的对象调用正确的析构函数。如果没有虚拟析构函数,则只调用基类析构函数,而不调用派生对象的析构函数。
在狗里:
void Fetch() const { cout << "fetch" << endl; }主要是:
shelter.Select(0)->Speak();
shelter.Select(1)->Speak();
shelter.Select(0)->Fetch();
shelter.Select(1)->Fetch();发布于 2014-04-02 09:51:43
编辑:
您可以尝试使用dynamic_cast将Animal对象转换为Dog,然后调用fetch方法:
Dog *foo = dynamic_cast<Dog*>(shelter.Select(1));
if (foo) {
foo->Fetch();
}如果dynamic_cast失败,它将返回null,因此在使用对象之前确保检查对象是否不是null。有关dynamic_cast的更多信息,请查看这里。
您可以向您的虚拟接口添加一个Animal函数:
class Animal {
public:
virtual void speak();
};另外,在一个不相关的注意事项上,您的speak方法似乎没有修改对象,所以您应该考虑将它们作为const
class Animal {
public:
virtual void speak() const;
};您可以找到关于const-正确性这里的更多信息。
发布于 2014-04-02 09:57:14
正如Aliou注意到的那样,speak应该在Animal中声明为virtual,否则层次结构是无用的,或者,换句话说,不存在多态性。
使用Animal测试Dog是否是Dog(同时进行上播)是一个需要考虑的选项。不漂亮,但很管用。
Dog *dog = dynamic_cast<Dog*> shelter.Select(1);
if (dog) dog->Fetch();(指向指针的dynamic_cast从不抛出,就像其他人建议的那样.)
另一种解决方案是在virtual Fetch中定义Animal,可能是NOP ({}),所以您不必在不提取的动物中定义它。
https://stackoverflow.com/questions/22807551
复制相似问题