将c++接口实例化为子类
Instantiating c++ interface as a child class
我有一个接口,我们叫它Creature
,它有虚函数,使得它是抽象的。
我有这个接口的子类,如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++中,你必须意识到值和引用语义之间的区别,而在解释语言中,你倾向于只处理引用语义(除了一些奇怪的情况,普通的旧数据对象具有值语义,但除了点)。
在c++中所有的对象都是值,例如一个对象永远不能是null
,这意味着声明指定了存储需求。考虑下面的
struct creature {
};
struct dog : public creature {
float cuteness;
};
狗的存储需求与生物不同,即使允许转换,也会导致切片。比如,狗狗会叫还是会沉默?# 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);
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- C++包括类名间距和类实例化
- 如何使用其中一个具体类实例化抽象类?
- 不带尖括号的模板类实例化
- 返回具体子类实例的 C++ 虚拟类函数
- 使用父类实例化的向下转换对象
- 模板类实例化中的指针转换无效
- 将子类实例保存在父类型变量中并通过父变量使用 Child 函数?
- 类的私有成员在我的类实例化期间更改,即使他们不应该
- 反向函数不反转类实例化的引用字符串
- 在类实例化时生成一个数字
- 谷歌测试 - 为模板类实例化生成值
- 使用派生类实例化基类,而不在对象定义中使用指针
- 模板类实例化如何与类继承协同工作
- 枚举器而不是用于类实例化的构造函数
- 使用std :: make_shared抽象类实例化的错误
- 通过纯虚拟函数防止类实例化
- C 11枚举类实例化
- 阿达水果示例中的 Bizare 类实例化
- 从标头中的类实例化对象