我自己学习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 ++中抽象类的文章,但我无法让它工作。
你能告诉我实现这个目标的正确方法吗?
答案 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语义(注意循环)。