2017-04-21 82 views
1

我有许多代表不同种类的动物的类。这个想法是,如果两个相同物种的动物相遇,那么这个物种的新动物就应该被创造出来 - 这意味着我想在这种情况下创造一个新的特定阶层的动机。如果熊会遇到,我想创建熊的新实例,当蝙蝠遇见新的蝙蝠实例。基于现有实例创建类的新实例

如何在不重复代码的情况下实现此目标?我想避免为每个类(动物)制定个体条件。我正在寻找解决方案,根据现有实例的类自动创建一个类的新实例。

+2

看起来你正在寻找[这](http://stackoverflow.com/questions/5148706/copying-a-polymorphic-object-in-c ) – NathanOliver

+0

您描述的场景听起来很像双派。我建议你查找一下。 –

+0

很大程度上取决于你说“见面”时的确切含义。如果两个“动物”都是“熊”,你是否有两个“动物”实例,并且想要创建一个新的“熊”实例?如果是这样,如果其中一个不是“熊”,会发生什么? –

回答

2

既然你知道,无论父对象必须有相同的类型,你不太需要通常的双调度解决方案 - 这些都是为了应付所有可能的组合。

我们只是使用克隆模式的稍微修改后的变体。 Animal,基类,得到一个纯虚克隆功能:

struct Animal { 
    virtual std::unique_ptr<Animal> mateWith(Animal const &other) const = 0; 
}; 

然后,每个子类实现此方法,通过RTTI检查其他Animal实际上是正确的类型:

struct Bear : Animal { 
    std::unique_ptr<Animal> mateWith(Animal const &other) const override { 
     auto &otherBear = dynamic_cast<Bear const &>(other); 
     return std::make_unique<Bear>(*this, otherBear); 
    } 
}; 

这将如果另一只动物不是熊,则扔掉std::bad_cast。您也可以与其他一些错误处理替换此:

struct Bear : Animal { 
    std::unique_ptr<Animal> mateWith(Animal const &other) const override { 
     auto *otherBear = dynamic_cast<Bear const *>(&other); 
     if(!otherBear) { 
      // This is not a bear! 
     } 

     return std::make_unique<Bear>(*this, *otherBear); 
    } 
}; 
1

您可以使用一般以下比较类型:

#include <typeinfo> 

if (typeid(YourClass1) == typeid(YourClass2)) 
// do something 

要创建一个新的实例,一个纯粹的虚拟克隆添加到您的基类,然后在每一个动物实施。

您也可以将名称字段添加到基类,并与之相比较。

class Animal{ 
public: 
    virtual shared_ptr<Animal> clone() = 0; 
    virtual const string & getname() = 0; 
}; 
class Bear: public Animal{ 
public: 
    virtual shared_ptr<Animal> clone() 
    { 
     return shared_ptr<Animal>(new Bear()); 
    } 
    virtual const string & getname() 
    { 
     return "bear"; 
    } 
}; 


int main(int argc, const char * argv[]) 
{ 
    Bear b1; 
    Bear b2; 
    shared_ptr<Animal> b3; 
    if (b2.getname() == b2.getname()) 
     b3 = (b1.clone()); 
    ... 
} 
+0

但是这个解决方案需要为每个类创建新的方法。我正在寻找解决方案,现有实例的类将被检测到,然后自动创建同一类的新实例。 – Sigger

+0

在这种情况下,您可以使用typeid(YourClass1).name获取名称,然后使用返回的字符串从Factory类中获取新的类实例,如上所述。由于编译器必须在编译器时知道类型,因此不允许完全动态创建。祝你好运! – didiz