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

C++ equivalent for simple Java polymorphism

本文关键字:Java 多态性 简单 等价于 C++      更新时间:2023-10-16

我在C++中处理一个看似简单的任务。我正在努力实现基本的OOP多态性。

考虑一下这个Java示例:

interface Bob
{
   void foo();
}
class ActualBob implements Bob
{
   void foo()
   {
      /* I like foo things */
   }
}
class Jane
{
    Bob 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

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

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

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

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

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

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

class Jane
{
public:
    Bob bob;
};

然而,试图将polymorphich对象存储在bob中会导致对象切片,从而降低多态性。为了保留它,请使用指向Bob的指针或引用。

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

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

你几乎做到了。问题是,在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对象,这些对象在某种程度上是由智能指针管理的。因此,与其讨论规则(析构函数、复制构造函数、运算符赋值和族),不如使用其中一个:

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

希望这能有所帮助。