简单Java多态性的C ++等价物

时间:2016-01-01 20:30:04

标签: java c++ polymorphism

我正在努力克服C ++中看似简单的任务。我试图实现基本的OOP多态性。

考虑这个Java示例:

interface Bob
{
   void foo();
}

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

class Jane
{
    Bob bob;
}

Jane可以拥有任何Bob,轻松:

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

现在,在C ++中,这似乎有点涉及...... 为了获得上述行为,我需要输入什么内容?

换句话说,我想拥有一个抽象基类的成员变量,但是想用它们做实际的实现。

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

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

class Jane
{
public:
    Bob bob;
}

在这里采取捷径,但我想在C ++中做:

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

另外,我可以拥有包含std::vector<Bob>个实例的ActualBob吗?

3 个答案:

答案 0 :(得分:6)

使用指针,智能指针,如下所示:

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;
}
  

在这里采取捷径,但我想用C ++做:

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

你可以这样做:

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

另外,我可以拥有包含std::vector<Bob>个实例的ActualBob吗?

是的,经过一些修改后,您可以拥有std::vector<Bob*>(但您必须自己释放内存),或者更好的是一些智能指针,例如std::vector<std::unique_ptr<Bob>>

答案 1 :(得分:1)

如果Bob是非多态的,那么您的代码就可以了:

class Jane
{
public:
    Bob bob;
};

但是,尝试在bob中存储多态对象会导致对象切片,这会丢弃多态性。为了保留它,请使用指针或对Bob的引用。

根据Bob的所有权,您可以使用不同类型的指针,甚至是引用。例如,如果Bob是动态分配的,并且可以在Jane的多个实例之间共享,则使用std::shared_ptr<Bob>是合适的:

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

答案 2 :(得分:1)

你几乎拥有它。问题是,在Java中似乎不必使用任何东西来创建多态对象,而实际上在Java中所有变量都是引用。 Java引用是具有较少功能的C ++指针。

在C ++中,当您键入Bob bob;时,您实际上是在左侧创建精确类型的对象。当你使用指针代替时,在右边你可以有一个 Bob 对象(在这种情况下这是不可能的,因为类 Bob 有一个纯虚方法)或任何其他子类。

所以,在你的代码中:

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

    Bob * bob;
}
但是,我们在没有任何警告的情况下遇到了另一种危险的情况。 Java有一个垃圾收集器,基本上意味着删除了任何未引用的对象。这不是在C ++中自动完成的,因此我们必须使用delete运算符手动完成。或者在这种情况下可能是智能指针:它们在C ++中表现自动删除对象。我们有std::unique_ptr<>可用,正是这样做的。确实存在其他方案,例如复制 Jane 对象,这些对象在某种程度上由智能指针管理。因此,不要谈论rules(析构函数,复制构造函数,运算符赋值和族),而是使用其中一个:

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

    unique_ptr<Bob> bob;
}

unique_ptr<>智能指针捕获->的使用(从技术上讲,它有箭头运算符重载),因此在语法上使用常规指针非常熟悉。现在:

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

另外,我可以拥有包含ActualBob的std::vector<Bob>吗?   实例

当然,但必须以与上面相同的方式更改代码:您必须使用std::vector<Bob *>,并自行释放成员指向的对象。或者,您可以再次使用智能指针,如:std::vector<unique_ptr<Bob>>

希望这有帮助。