【问题标题】:C++ changing type in constructor?C ++在构造函数中更改类型?
【发布时间】:2012-07-02 07:29:35
【问题描述】:

我有一个抽象类Engine3D,它的结构(Vector3D 等)在头文件中。

现在,我有一个该类的实现,ConcreteEngine3D : Engine3D。此外,我还有其他类,例如 ConcreteVector3D : Vector3D,它们具有将在 ConcreteEngine3D 内部使用的其他成员和方法(为了这个示例,假设它是 float lengthcalculateLength())。

在 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!
}

另外,我不想在Engine3DConcreteEngine3D 中使用工厂。我想允许“用户”按照我在第一个代码中编写的方式创建 Vector3D

【问题讨论】:

  • 也许最好写出一个可以工作的小程序来演示这个问题。您要达到的目标不是很清楚。
  • 现在您正在分配指向不应编译的值 (Vector3D vector = new Vector3D...) 的指针。
  • 您可以覆盖Vector3Doperator new 让它分配sizeof(ConcreteVector3D)。然后,在 Vector3D 中,创建 ConcreteVector3Dmemcpy(this,...)。但这将是可怕的。你不会为你的用户提供这样的惊喜——阅读Principle of Least Astonishment。我建议您重新考虑使用工厂 - 使用 Vector3D* GetVector3D() 方法。在单独的 cpp 文件中定义它,并让它返回一个指向 ConcreteVector3D 对象的指针。这样,您将不再依赖 ConcreteVector3D

标签: c++ class types polymorphism


【解决方案1】:

听起来您想使用抽象工厂模式来实例化您的对象,这样您就不必直接调用具体类的构造函数。然后,如果您想更改实现接口的具体类型,您只需要链接到抽象工厂的不同实现,或者在运行时选择合适的工厂实现。

编辑:错过了“不想使用工厂”...无论如何,您将需要某种重定向,因为构造函数将返回您实例化的类型。您可以获得的最接近的可能是为类 Vector3D 创建一个静态工厂方法“create”,该方法返回一个指向 Vector3D 的指针,但在内部创建一个具体实现类的实例。如果您这样做,最好将 Vector3D 的构造函数设为私有,以防止以“错误的方式”创建向量。

【讨论】:

  • “另外,我不想使用工厂...” :)
  • 谢谢,我也在考虑。不幸的是,这将使我使用 Vector3D v = MyFactory::create(),而不是构造函数。难道没有什么办法可以代替吗?
  • @PolGraphic 如果您不对第一个示例代码进行任何修改,就不可能实现您想要实现的目标。工厂是正确的解决方案。构造函数不是多态的。他们将始终构建他们告诉您他们将构建的东西。
  • +1 代表工厂。 “不想使用工厂”是一个不好的论点(不合理)。沉迷于语法只会让自己陷入困境。
【解决方案2】:

Andrew Tomazos,关于不清楚的文字 - 抱歉:/

我必须同意 Giraffe 船长的观点,如果没有对 main.cpp 进行任何更改,我将无法实现它。我使用了稍微修改的工厂模式:

我必须创建 Vector3D::create() 静态函数,该函数将调用 Engine3D::convert() 并返回结果。所以代码将是:

#include "ConcreteEngine3D.h"
Engine3D * engine;
...
int main(){
    engine = new ConcreteEngine3D();
    Vector3D vector = Vector3D::create(engine, 10, 5, 2);
}

Vector3D::create: 内部

return engine->convert(new Vector3D(x,y,z));

这将产生 ConcreteVector3D(因为引擎是 ConcreteEngine3D 类型)。

main.cpp 中的最小更改,可接受(main.cpp 中未提及 ConcreteVector3D)。

再次感谢大家的帮助! :-)

【讨论】:

  • 好的,谢谢。我先忘记了,现在我接受了你的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-08
  • 2011-02-10
  • 1970-01-01
  • 2012-05-12
  • 2018-07-26
相关资源
最近更新 更多