将C++接口实例化为子类

问题描述:

我有一个接口,我们称其为Creature,他具有虚拟函数,使其成为抽象类。将C++接口实例化为子类

我有这个接口的子类,如DogCatPig

由于无法将变量thing声明为抽象类型Creature,编译器似乎不喜欢以下行。

Creature thing = Dog(); 

我知道我不能实例化接口等,但是这仅仅是一个Dog被声明为Creature

我需要有对所有的孩子一个申报工作的一些方法(即能够把Dog()Cat(),或Pig()其中Dog()是线以上)。

这可以在c + +中完成,或者我滥用继承和接口完全?

对象类型本身在C++中不是多态的。您给出的行声明了一个Creature对象,然后尝试用Dog对象初始化它。如果Creature不是抽象的,这会导致分片 - thing不会是Dog,它只会是Creature。由于它是抽象的,因此无论如何你都不能有一个对象Creature

您需要为多态行为使用指针或引用。考虑到例如:

Creature* thing = new Dog(); 

现在可以提领thing并把它作为一个Creature,即使它的动态类型Dog。但是,通常不推荐使用像这样的原始指针,因为您必须在某个时刻手动确保对象为deleted。所有权可能会变得混乱。最好的办法是把它放在一个智能指针,如:

std::unique_ptr<Creature> thing(new Dog()); // or std::make_unique when we have it 

在这里,我已经证明std::unique_ptr,但智能指针的选择将取决于所有权语义该对象。一个常见的选择是std::shared_ptr

若要引用表现多态:

Dog dog; 
Creature& thing = dog; 
// Can now use dog as a Creature 
+0

有趣!我对最后提到的引用有点好奇。如果'Creature'有一个名为'talk()'和'Dog'的虚拟方法覆盖它,会调用'thing'的树皮调用'Creature's或'Dog's? – 2013-03-23 20:57:28

+0

@CoreyMaddieBesmer它会调用'Dog',因为当通过指针或引用调用虚拟成员函数时,会查找对象的* dynamic *类型。 “东西”的动态类型是“狗”。 – 2013-03-23 21:01:07

在C++中,你必须认识到不同的价值和参考语义之间,其中,在interpretet的语言,你往往只是处理引用语义(除了一些奇怪的具有价值语义但除点之外的普通旧数据对象的情况)。

在C++中,所有对象都是值,例如一个对象永远不可能是null,这意味着声明指定了存储需求。 考虑对狗以下

struct creature { 
}; 

struct dog : public creature { 
    float cuteness; 
}; 

的存储需求比生物的不同,即使您允许的转换,这将导致切片。 例如,将fido树皮或保持沉默? 的#include

class creature { 
public: 
    virtual void speak() { 
     std::cout << "..." << std::endl; 
    } 
}; 

class dog : public creature { 
public: 
    virtual void speak() { 
     std::cout << "woof!" << std::endl; 
    } 
}; 

int main(int argc, const char *argv[]) { 
    creature fido; 
    fido = dog(); 

    fido.speak(); 
    return 0; 
} 

但是如果你只需有一个指针或参考对象是另一回事。 通过指针。

creature* fido = new dog(); 
fido->speak(); 
delete fido; 

作为参考。

dog fido; 
creature& c = fido; 

c.speak(); 

超出此问题的范围,但可以选择一个智能指针。

std::unique_ptr<creature> fido(new dog);