简体   繁体   English

C ++相当于简单的Java多态

[英]C++ equivalent for simple Java polymorphism

I'm struggling with a seemingly simple task in C++. 我正在努力克服C ++中看似简单的任务。 I'm trying to achieve basic OOP polymorphism. 我正在尝试实现基本的OOP多态性。

Consider this Java example: 考虑这个Java示例:

interface Bob
{
   void foo();
}

class ActualBob implements Bob
{
   void foo()
   {
      /* I like foo things */
   }
}

class Jane
{
    Bob bob;
}

Jane can have any Bob, easypeasy: 简可以有任何鲍勃,很容易:

Jane jane = new Jane();
jane.bob = new ActualBob();
jane.bob.foo(); // actualbob things

Now, in C++ this seems somewhat more involved.... What do I have to type to get the above behaviour? 现在,在C ++中,这似乎有点涉及......我需要输入什么来获得上述行为?

In other words, I would like to have member variables of an abstract base class, but would like to do actual-implementation things with them. 换句话说,我想有一个抽象基类的成员变量,但是想用它们做实际的实现。

class Bob
{
public:
   virtual void foo() = 0;
}

class ActualBob : public Bob
{
public:
    void foo(){/* I like foo things */}
}

class Jane
{
public:
    Bob bob;
}

Taking shortcuts here, but I'd like to do, in C++: 在这里采取捷径,但我想用C ++做:

jane.bob.foo(); // does ActualBob things

Also, can I have a std::vector<Bob> which contains ActualBob instances? 另外,我可以有一个包含ActualBob实例的std::vector<Bob>吗?

Use pointers, smart pointers, like this: 使用指针,智能指针,如下所示:

class Bob
{
public:
   virtual void foo() = 0;
}

class ActualBob : public Bob
{
public:
    void foo() override {/* I like foo things */}
}

class Jane
{
public:
    std::unique_ptr<Bob> bob;
}

Taking shortcuts here, but I'd like to do, in C++: 在这里采取捷径,但我想用C ++做:

 jane.bob.foo(); // does ActualBob things 

You can do this: 你可以这样做:

jane.bob->foo(); // does ActualBob things, if `bob` is a pointer to ActualBob

Also, can I have a std::vector<Bob> which contains ActualBob instances? 另外,我可以有一个包含ActualBob实例的std::vector<Bob>吗?

Yes, with some modifications, you can have a std::vector<Bob*> (but you must free memory on your own) or, better, some smart pointers, like std::vector<std::unique_ptr<Bob>> . 是的,通过一些修改,你可以有一个std::vector<Bob*> (但你必须自己释放内存),或者更好的是,一些智能指针,比如std::vector<std::unique_ptr<Bob>>

Your code would be fine if Bob were non-polymorphic: 如果Bob是非多态的,那么你的代码就可以了:

class Jane
{
public:
    Bob bob;
};

However, trying to store a polymorphich object in bob would lead to object slicing , which drops polymorphism. 但是,尝试在bob存储多态对象会导致对象切片 ,从而丢弃多态。 In order to preserve it, use a pointer or a reference to Bob . 为了保留它,请使用指针或Bob的引用。

Depending on the ownership of Bob you could use a different kind of pointer, or even a reference. 根据Bob的所有权,您可以使用不同类型的指针,甚至是引用。 For example, if Bob is allocated dynamically, and could be shared among multiple instances of Jane , using std::shared_ptr<Bob> would be appropriate: 例如,如果Bob是动态分配的,并且可以在Jane多个实例之间共享,则使用std::shared_ptr<Bob>是合适的:

class Jane
{
public:
    Jane(Bob* bPtr) : bob(bPtr) {}
    std::shared_ptr<Bob> bob;
};

You nearly have it. 你几乎拥有它。 The problem is that it seems in Java that you don't have to use anything in order to create a polymorphic object, while actually in Java all that variables are references. 问题是,在Java中,您似乎不必使用任何东西来创建多态对象,而实际上在Java中所有变量都是引用。 Java references are C++ pointers with less capabilities. Java引用是具有较少功能的C ++指针。

In C++, when you type Bob bob; 在C ++中,键入Bob bob; , you're actually creating an object of the precise type on the left. ,你实际上是在左边创建一个精确类型的对象。 When you use a pointer instead, then at the right you can have a Bob object (which would be impossible in this case, since the class Bob has a pure virtual method), or any other subclass. 当您使用指针时,在右侧,您可以拥有一个Bob对象(在这种情况下这是不可能的,因为Bob类具有纯虚方法)或任何其他子类。

So, in your code: 所以,在你的代码中:

class Jane
{
public:
    Jane()
        { bob = new ActualBob(); }

    Bob * bob;
}

We have, however, run into a different, dangerous scenario without warning. 但是,我们在没有任何警告的情况下遇到了另一种危险的情况。 Java has a garbage collector, basically meaning that any object which is not referenced is deleted. Java有一个垃圾收集器,基本上意味着删除了任何未引用的对象。 This is not done automatically in C++, so we have to do it manually, using the delete operator. 这不是在C ++中自动完成的,因此我们必须使用delete运算符手动完成。 Or maybe a smart pointer in this case: they behave in C++ doing the deletion of the object automatically. 或者在这种情况下可能是智能指针:它们在C ++中表现自动删除对象。 We have std::unique_ptr<> available, doing exactly that. 我们有std::unique_ptr<>可用,正是这样做的。 There are indeed other scenarios, such as copying Jane objects, which are somewhat managed by a smart pointer. 确实存在其他方案,例如复制Jane对象,这些对象在某种程度上由智能指针管理。 So instead of talking about rules (destructors, copy constructors, operator assignment, and family), let's use one of them: 因此,不要谈论规则 (析构函数,复制构造函数,运算符赋值和族),而是使用其中一个:

class Jane
{
public:
    Jane()
        { bob.reset( new ActualBob() ); }

    unique_ptr<Bob> bob;
}

The unique_ptr<> smart pointer captures the use of -> (technically, it has the arrow operator overloaded), so its use is syntactically familiar to the use of a regular pointer. unique_ptr<>智能指针捕获使用-> (技术上,它有箭头操作符重载),因此它的使用在语法上熟悉常规指针的使用。 Now: 现在:

Jane jane = new Jane();
jane.bob->foo();

Also, can I have a std::vector<Bob> which contains ActualBob instances? 另外,我可以有一个包含ActualBob实例的std::vector<Bob>吗?

Sure, but have to change your code in the same way as above: you would have to use std::vector<Bob *> , and free the objects pointed by the members yourself. 当然,但必须以与上面相同的方式更改代码:您必须使用std::vector<Bob *> ,并自行释放成员指向的对象。 Or, you could use again a smart pointer, as in: std::vector<unique_ptr<Bob>> . 或者,您可以再次使用智能指针,如: std::vector<unique_ptr<Bob>>

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM