Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在派生类C++;_C++_Virtual_Base Class - Fatal编程技术网

C++ 在派生类C++;

C++ 在派生类C++;,c++,virtual,base-class,C++,Virtual,Base Class,我有一些不同的对象,它们的类型都是Zoo,它们有一个成员变量Collection=vector。我有一个动物园的例子,所有的元素都是动物,一个所有的元素都是鸟,还有一个所有的元素都是蝙蝠。鸟类和蝙蝠都起源于动物 我希望有一个方法fly(),我可以调用所有的鸟类和蝙蝠,但我不确定最好的方法是什么。当我在我的鸟类/蝙蝠动物园中循环时,我应该投下吗?像这样: Bird thisBird = static_cast<Bird>(Collection[i]); thisBird.fly();

我有一些不同的对象,它们的类型都是
Zoo
,它们有一个成员变量
Collection=vector
。我有一个动物园的例子,所有的元素都是动物,一个所有的元素都是鸟,还有一个所有的元素都是蝙蝠。鸟类和蝙蝠都起源于动物

我希望有一个方法
fly()
,我可以调用所有的鸟类和蝙蝠,但我不确定最好的方法是什么。当我在我的鸟类/蝙蝠动物园中循环时,我应该投下吗?像这样:

Bird thisBird = static_cast<Bird>(Collection[i]);
thisBird.fly();
Bird thisBird=static_cast(集合[i]);
这只鸟;
。。。或者我可以在Animal上有一个虚拟函数,它只在派生自它的类上实现


想法,以及为什么它们是“好代码”的理由,欢迎

并非所有动物都能飞,因此没有必要为了一般目的而尝试执行特定行为(即所有动物之间不常见的行为)。如果你有一个动物类(或它们的派生类)的集合,它的目的是允许它们做一个共同的行为(每个派生类的实现方式不同)


你可以实现一个
flyible
接口(即抽象类),并只对真正会飞的动物进行扩展。而不仅仅是将它们保存在为这些动物指定的另一个集合中(即)

您可能不希望像
Bird
Bat
这样的层次结构起源于
Animal
,而不需要
fly()
方法,这些方法是从低级类中声明的。这样一来,您就失去了统一层次结构的意义

您可以执行以下任一操作:

class Animal {
    virtual bool canFly() { return false; }
    virtual void fly() {throw Exception( "Sorry babe, I don't fly"); }
}
并在
Bird
Bat
中覆盖
fly

这将导致为狗和猫实现方法
fly()。因此,也许您可以创建新的类
传单
,它将声明此方法:

class Flyer : public Animal {
    virtual void fly() = 0;
}

class Bat : public Flyer {}
class Bird : public Flyer {}
这与更详细的生物学分类不一致,如爬行动物、哺乳动物

另一个技巧可能是提出类似于
move()
的方法,dog将其实现为
run()
,bird实现为
fly()
,所有这些都具有统一的接口

另一件事是,我认为询问狗是否会飞是一个有效的问题,所以我认为像
dog.canFly()
这样的方法应该在您的代码中实现,作为动物的一部分

考虑到所有这些因素,我认为:

// Your base animal
class Animal {
    virtual bool canFly() {return false;}
};

// Any animal that could fly, just abstract class
class Flyer {
    virtual void fly() = 0;
}

// Ants, flies etc.; real biological hierarchy
class Insect : public Animal {}
class Mammals : public Animals {}
class Birds : public Animals {}

// And now flying bird :
class Bird : public Birds, public Flyer {
    virtual bool canFly() {return true; }
    virtual void fly() {...}
}

// And flying insect
class Fly : public Insect, public Flyer {
    virtual bool canFly() {return true; }
    virtual void fly() {...}
}
然后你就可以这样做了(基于我恐怕你必须使用指针):

但是,如果您将
动物
鸟类
传单
作为
鸟类
传单
的一部分,则:

class Animal {
public:
    virtual bool canFly() const {return false;}
};

class Flyer : virtual Animal {
public:
    virtual bool canFly() const {return true;}
    virtual void fly() {cout << "Flying" << endl; }
};

class Bird : virtual public Birds, virtual public Flyer {

}; 

// Warning  1   warning C4250: 'Bird' : inherits 'Flyer::Flyer::canFly' via dominance

请注意,
传单
仍然很重要,因为
昆虫
提供的
苍蝇
哦,是的,
动物
可能具有虚拟功能:

virtual void move(){}
virtual void fly(){}
当你命令狗飞的时候,它什么也不做。当你命令一只鸟移动时,它也可以调用
fly()

为飞行的动物正确定义
fly()
,并且
collection[i]->fly()
将做正确的事情。这样你的代码就简单了

但要做到这一点,您的集合必须收集指向动物的指针,而不仅仅是动物对象。 例如:

#include <vector>
#include <memory>
#include <iostream>  
using namespace std;
struct Animal{virtual void fly(){}};
struct Bird:public Animal{void fly(){cout<<"fly\n";}};
int main()
{
  vector<unique_ptr<Animal>> Colection(1);
  Colection[0].reset( new Bird ); 
  Colection.push_back(unique_ptr<Animal>(new Bird) );
  Colection.push_back(unique_ptr<Animal>(new Animal) );
  Colection[0]->fly(); 
  Colection[1]->fly(); 
  Colection[2]->fly();   
}
#包括
#包括
#包括
使用名称空间std;
结构动物{virtualvoid fly(){};
结构鸟:公共动物{void fly(){coutfly();
collection[2]->fly();
}
阅读其他答案,我可以建议您执行以下操作

struct Animal    {virtual bool fly(){return false;     }};
struct Bird:public Animal{bool fly(){cout<<"fly\n";return true;}};
struct Animal{virtual bool fly(){return false;};

struct Bird:public Animal{bool fly(){coutYou正在将可能按值多态使用的对象放在一个容器中。每个动物园的
集合
向量中只包含相同类型的动物(通用、鸟类或蝙蝠),不过..如果不是通过铸造,你对我应该怎么做有什么建议吗?…啊-应该是收藏。已编辑以更正this@tiswas:这不是重点。如果你有一个
向量
,你把一只
推进去,那只鸟会被切成薄片,而你的向量只会持有一只不能再移动的
动物
r回到
Bird
。仔细阅读切片问题;解决方案是在向量中保留(智能?)指针。我明白了。那么回到我的问题-我应该怎么做?这不要求每个动物园都有不同的类型吗,因为它们的成员变量集合有不同的类型(向量与向量相反)?这在很大程度上取决于你的动物园在你的程序中扮演什么角色。我相信如果你设计正确,在这种飞行环境中,你将只有一种动物园类型。投票者会从阴影中走出来解释吗?嗯,我喜欢这个声音,但是@Jon提到:“如果你有一个向量,你把一只鸟推进去,那只鸟会被吃掉。”切片后,你的向量将只容纳一个不能再扔回鸟身上的动物。@tiswas说实话,我一直在使用指针,这些都没有问题。只是为了好玩,实现复制构造函数,看看它被调用了多少次。:@Vyktor似乎有意义将canFly默认实现返回true到Flyer中(默认情况下,传单可以飞行!)@Ricibob试图将其添加到answer中,但如果没有一个好的答案,它会变得越来越复杂。这就是我的观点“没有..,它会越来越复杂”。为什么不将virtual void fly(){}添加到基类中?为什么添加canFly()会更好?这对我来说似乎是最简单的赌注,虽然我没有使用C++11,所以我想我只需要
向量集合;
virtual void move(){}
virtual void fly(){}
#include <vector>
#include <memory>
#include <iostream>  
using namespace std;
struct Animal{virtual void fly(){}};
struct Bird:public Animal{void fly(){cout<<"fly\n";}};
int main()
{
  vector<unique_ptr<Animal>> Colection(1);
  Colection[0].reset( new Bird ); 
  Colection.push_back(unique_ptr<Animal>(new Bird) );
  Colection.push_back(unique_ptr<Animal>(new Animal) );
  Colection[0]->fly(); 
  Colection[1]->fly(); 
  Colection[2]->fly();   
}
struct Animal    {virtual bool fly(){return false;     }};
struct Bird:public Animal{bool fly(){cout<<"fly\n";return true;}};