将C++接口实例化为子类
我有一个接口,我们称其为Creature
,他具有虚拟函数,使其成为抽象类。将C++接口实例化为子类
我有这个接口的子类,如Dog
,Cat
和Pig
。
由于无法将变量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
。但是,通常不推荐使用像这样的原始指针,因为您必须在某个时刻手动确保对象为delete
d。所有权可能会变得混乱。最好的办法是把它放在一个智能指针,如:
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
在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);
有趣!我对最后提到的引用有点好奇。如果'Creature'有一个名为'talk()'和'Dog'的虚拟方法覆盖它,会调用'thing'的树皮调用'Creature's或'Dog's? – 2013-03-23 20:57:28
@CoreyMaddieBesmer它会调用'Dog',因为当通过指针或引用调用虚拟成员函数时,会查找对象的* dynamic *类型。 “东西”的动态类型是“狗”。 – 2013-03-23 21:01:07