如何在c ++中正确创建基类?

时间:2012-01-02 23:46:10

标签: c++ oop interface

我自己学习C ++,“创建”RPG。但是,我坚持创建一个名为Item的类,它将成为所有游戏项的基类(或者如果它是在Java中的接口)。这是我的代码:

class Item {

    public:

    virtual const char* GetName() = 0;
};

我读过一些关于“纯虚拟”功能的内容,我正在使用它。

我的角色类,我使用我的项目:

class Character {

  // some code...

  void ConsumeItem(Item item);

}

但是gcc给了我这个错误:

g++ -Wall -o adventure character.cpp adventure.cpp
In file included from adventure.cpp:3:0:
character.h:36:24: error: cannot declare parameter ‘item’ to be of abstract type ‘Item’
item.h:4:7: note:   because the following virtual functions are pure within ‘Item’:
item.h:11:22: note:     virtual const char* Item::GetName()

我对C ++中的OOP很新,因为它与Java非常不同。我已经阅读了一些关于C ++中抽象类的文章,但我无法让它工作。

你能告诉我实现这个目标的正确方法吗?

6 个答案:

答案 0 :(得分:3)

在Java中,执行类似的操作将创建对Item的引用,然后您可以为其分配具体子类的实例。

但是在C ++中,Item item创建Item 的实例,由于Item包含纯virtual函数,因此不允许这样做

要避免此问题,您需要使item成为指针或引用,例如:

void ConsumeItem(Item *item);

答案 1 :(得分:2)

通常,如果您有类层次结构,则希望使用引用或指向对象的[智能]指针。在您的代码摘录中,Item是一个抽象基类,因此无法创建。但是,ConsumeItem函数的Item参数是按值传递的:没有“&”和“*”对象是C ++中的值。您可能希望使用以下方法之一传递参数:

  • void ConsumeItem(Item& item) //通过引用传递
  • void ConsumeItem(Item const& item) //通过引用传递不可修改的对象
  • void ConsumeItem(Item* item) //使用指针传递
  • void ConsumeItem(std::shared_ptr<Item> item) //使用智能指针传递
顺便说一句,你不容易想到的是:如果你的基类有任何虚拟功能,那么你也可以使用析构函数虚拟化!否则你几乎肯定会遇到未定义的行为,这通常是一件坏事。也就是说,在Item班级中添加:

virtual ~Item() {} // can also be defined out of line but always has to be defined

答案 2 :(得分:0)

由于Item是一个抽象类,你不能使用它的实例,你应该使用指针*或引用&

在你的情况下,你正在传递它的一个实例,你应该传递一个指针:

class Character {

  // some code...

  void ConsumeItem(Item* item);

}

因此,您实际上是将一个指针传递给一个非抽象类并继承自Item的类的对象。

答案 3 :(得分:0)

ConsumeAccept收到Item的引用(或指针):

void ConsumeItem(Item& item);

Item是多态的,它的确切大小取决于实现它的派生类,因此不允许按值传递它(理论上如果它没有纯虚函数,理论上是可能的,但效果不是预期的。)

确保您了解C ++中的指针,引用和值类型。在Java中,所有对象都被视为没有额外符号的引用(例如&)来表示这一点。差异至关重要。

答案 4 :(得分:0)

您不能实例化包含纯虚方法的类,而Item item将是这样的un实例。但是,您可以为它们创建指针,因此Item *item将起作用。

答案 5 :(得分:0)

为了在C ++中使用多态,你需要使用指针(或引用,但我现在要忽略它)。

您必须将多态对象存储为指针,将它们作为指针传递等等。

修改后的ConsumeItem将是:

class Character {

  // some code...

  void ConsumeItem(Item* item);

}

通过使用shared_ptr来避免内存泄漏,这将得到进一步改善。

class Character {

  // some code...

  void ConsumeItem(std::shared_ptr<Item> item);

}

将所有内容作为shared_ptr传递实际上非常接近Java语义(注意循环)。