C++ 访问抽象 class 指针向量的 subclass 的成员
C++ accessing member of subclass of abstract class pointer vector
此处错误:
Rocket.cpp:31:16: error: no member named 'getThrust' in 'RocketPart'
rocket[0]->getThrust();
当我想从 class Engine
通过 vector<RocketPart*> rocket
和 rocket[i]->getThrust()
访问 getThrust()
时,我从我的题。
我究竟做错了什么?是否可以通过 rocket[index]->getThrust() 访问它?
您需要添加
virtual float getThrust() = 0;
在你的 RocketPart
class 中。
此外,我认为完全没有理由使用虚拟继承(仅当您从多个 classes and 继承时才需要使用 The Diamond Problem),所以改为:
class Engine : virtual public RocketPart {
你应该没问题:
class Engine : public RocketPart {
我还建议查看您的内存分配 - 如果您的示例源代码不仅仅是一个示例(您正在泄漏 Engine
对象,也许vector<shared_ptr<Engine>>
会更好吗?)
class RocketPart
内部没有函数 getThrust()
,这就是为什么调用该函数的向量不起作用的原因。如果 getThrust()
是将在继承它的 classes 中使用的通用例程,则应将其作为虚函数添加到基 class 中,如下所示:
class RocketPart {
public:
RocketPart();
RocketPart(const RocketPart& orig);
virtual ~RocketPart();
virtual float getThrust();
virtual void print() = 0;
protected:
// some members
};
因为容器中存放的类型是RocketPart。
您需要向下转换指向 Engine 的指针。
所以而不是
rocket[0]->getThrust();
你需要写:
Engine *pPart = (Engine *) rocket[i]; //you can use also static_cast<> or dynamic_cast<>
pPart->getThrust();
使用 cast 时要小心:如果 rocket[i] 不是 Engine,程序可能会崩溃。
您收到的错误是正确的:class RocketPart
中没有名为 getThrust
的函数。您可以:
- 将
virtual float getThrust()
添加到您的 RocketPart
class。这可能不是一个好的解决方案,因为并非所有 RocketPart
都可以包含推力;但是,您可以简单地 return 0
从它,或使它成为一个纯虚函数(这意味着您将不再创建 RocketPart
对象
dynamic_cast
你的 RocketPart
对象变成 Engine
。这可以通过以下方式完成:
for (size_t r = 0; r < rocket.size(); ++r)
{
if (const Engine* engine = dynamic_cast<Engine*>(rocket[r]))
{
// able to successfully convert this RocketPart into an Engine
engine.getThrust();
}
}
您将无法施放任何 RocketPart*
不是 Engine
方法 getThrust() 是在引擎 class 中定义的,而不是在 RocketPart 中。
您需要移动基础 class RocketPart 中的方法,以便通过向量访问它。
或者,您也可以使用 "convert" 将 RocketPart 动态转换为引擎。
Engine* engine = dynamic_cast<Engine>(rocket[index]);
if (engine) {
engine->getThrust();
}
考虑到 dynamic_cast 的使用通常意味着糟糕的设计。
此处错误:
Rocket.cpp:31:16: error: no member named 'getThrust' in 'RocketPart'
rocket[0]->getThrust();
当我想从 class Engine
通过 vector<RocketPart*> rocket
和 rocket[i]->getThrust()
访问 getThrust()
时,我从我的题。
我究竟做错了什么?是否可以通过 rocket[index]->getThrust() 访问它?
您需要添加
virtual float getThrust() = 0;
在你的 RocketPart
class 中。
此外,我认为完全没有理由使用虚拟继承(仅当您从多个 classes and 继承时才需要使用 The Diamond Problem),所以改为:
class Engine : virtual public RocketPart {
你应该没问题:
class Engine : public RocketPart {
我还建议查看您的内存分配 - 如果您的示例源代码不仅仅是一个示例(您正在泄漏 Engine
对象,也许vector<shared_ptr<Engine>>
会更好吗?)
class RocketPart
内部没有函数 getThrust()
,这就是为什么调用该函数的向量不起作用的原因。如果 getThrust()
是将在继承它的 classes 中使用的通用例程,则应将其作为虚函数添加到基 class 中,如下所示:
class RocketPart {
public:
RocketPart();
RocketPart(const RocketPart& orig);
virtual ~RocketPart();
virtual float getThrust();
virtual void print() = 0;
protected:
// some members
};
因为容器中存放的类型是RocketPart。 您需要向下转换指向 Engine 的指针。 所以而不是
rocket[0]->getThrust();
你需要写:
Engine *pPart = (Engine *) rocket[i]; //you can use also static_cast<> or dynamic_cast<>
pPart->getThrust();
使用 cast 时要小心:如果 rocket[i] 不是 Engine,程序可能会崩溃。
您收到的错误是正确的:class RocketPart
中没有名为 getThrust
的函数。您可以:
- 将
virtual float getThrust()
添加到您的RocketPart
class。这可能不是一个好的解决方案,因为并非所有RocketPart
都可以包含推力;但是,您可以简单地return 0
从它,或使它成为一个纯虚函数(这意味着您将不再创建RocketPart
对象 dynamic_cast
你的RocketPart
对象变成Engine
。这可以通过以下方式完成:for (size_t r = 0; r < rocket.size(); ++r) { if (const Engine* engine = dynamic_cast<Engine*>(rocket[r])) { // able to successfully convert this RocketPart into an Engine engine.getThrust(); } }
您将无法施放任何 RocketPart*
不是 Engine
方法 getThrust() 是在引擎 class 中定义的,而不是在 RocketPart 中。 您需要移动基础 class RocketPart 中的方法,以便通过向量访问它。 或者,您也可以使用 "convert" 将 RocketPart 动态转换为引擎。
Engine* engine = dynamic_cast<Engine>(rocket[index]);
if (engine) {
engine->getThrust();
}
考虑到 dynamic_cast 的使用通常意味着糟糕的设计。