【发布时间】:2012-07-02 07:29:35
【问题描述】:
我有一个抽象类Engine3D,它的结构(Vector3D 等)在头文件中。
现在,我有一个该类的实现,ConcreteEngine3D : Engine3D。此外,我还有其他类,例如 ConcreteVector3D : Vector3D,它们具有将在 ConcreteEngine3D 内部使用的其他成员和方法(为了这个示例,假设它是 float length 和 calculateLength())。
在 main.cpp 我有代码:
#include "ConcreteEngine3D.h"
Engine3D * engine;
...
int main(){
engine = new ConcreteEngine3D();
Vector3D* vector = new Vector3D(engine, 10, 5, 2);
}
我希望变量 vector 的类型为 ConcreteVector3D*。
我需要ConcreteEngine3D 中的那个类型,但在 main.cpp 中我什至不应该知道它是那个类型,也不必使用像length 这样的扩展字段。此外,我不能在 main.cpp 中使用具体来自 ConcreteEngine3D.h(仅 Engine3D.h)的任何内容 - 这是为了灵活,更改实现必须意味着仅更改包含并与 new ConcreteEngine3D() 保持一致。
我不想修改上面的代码或Engine3D 的原始标题。
在Vector3D 的构造函数中,我总是放置一个指向Engine3D 对象的指针(我在这里给出ConcreteEngine3D 类型)。
也许我可以在Vector3D的构造函数中做一些事情来改变它的类型?
例如在构造函数内部调用Vector3D* Engine3D::convert(Vector3D v),该构造函数将从ConcreteEngine3D 中的Engine3D 继承(创建一个新的ConcreteVector3D 对象,其中包含来自Vector3D 的字段并返回它)。
当然,该代码不起作用:
Vector3D::Vector3D(Engine3D *engine){
//how to 'return' or 'convert' the type to the one that returns engine->convert(this);
}
所以基本上,我想得到下面代码的效果,但没有vector = engine->convert(vector)或Vector3D* vector2 = new ConcreteVector3D(engine, 10, 5, 2)这一行。
#include "ConcreteEngine3D.h"
Engine3D * engine;
...
int main(){
engine = new ConcreteEngine3D();
Vector3D* vector = new Vector3D(engine, 10, 5, 2); //produces Vector3D, not ConcreteVector3D
vector = engine->convert(vector); //cannot be here! but creates the right object
Vector3D* vector2 = new ConcreteVector3D(engine, 10, 5, 2); //also creates rights object, but cannot be here!
}
另外,我不想在Engine3D 或ConcreteEngine3D 中使用工厂。我想允许“用户”按照我在第一个代码中编写的方式创建 Vector3D。
【问题讨论】:
-
也许最好写出一个可以工作的小程序来演示这个问题。您要达到的目标不是很清楚。
-
现在您正在分配指向不应编译的值 (
Vector3D vector = new Vector3D...) 的指针。 -
您可以覆盖
Vector3D的operator new让它分配sizeof(ConcreteVector3D)。然后,在 Vector3D 中,创建ConcreteVector3D和memcpy(this,...)。但这将是可怕的。你不会为你的用户提供这样的惊喜——阅读Principle of Least Astonishment。我建议您重新考虑使用工厂 - 使用Vector3D* GetVector3D()方法。在单独的 cpp 文件中定义它,并让它返回一个指向ConcreteVector3D对象的指针。这样,您将不再依赖ConcreteVector3D。
标签: c++ class types polymorphism