C ++:通过向下转换为派生类来扩展对象

时间:2016-07-21 08:59:16

标签: c++ inheritance parent-child downcast

我想这是一个经典,但在我的情况下,我有限制,应该简化问题。

只是我在模块的输入处得到了一些结构A,并希望为它添加一些属性。所以我创建了一个扩展A的结构B,并添加了我需要的内容。

现在每当我调用一个期望B的方法但是我给A喂它时,编译器就不满意了:对象可能不是Bs,就像所有的猫都不是狮子一样。

但在我的情况下,我发誓所有As都是B,尽管属性较少。未找到的属性可以报告为未初始化,这很好,我也发誓我在初始化之前永远不会调用属性。基本上,在将A对象作为输入时,我首先要做的是填充剩余的B属性,这些属性是根据A属性计算的。我只是不想复制“我进入Bs”只是为了添加一些属性,因为As的属性会被复制到内存中。我也不会修改A的原始属性,我只是用它们来计算派生属性,然后传递并使用A属性和派生属性处理B对象。

示例:

来自普通的项目范围标题:

struct Rectangle {
    // Side lengths
    int a,b;
}

从本地标题:

struct LocalRectangle : Rectangle {
    int area;
}

void updateModule(Rectangle inputRect);

来自当地来源:

void updateModule(Rectangle inputRect) {
    LocalRectangle r = (LocalRectangle)inputRect;
    r.area = r.a*r.b;
    // More processing ...
}

我该怎么做?

提前致谢,

查尔斯

2 个答案:

答案 0 :(得分:1)

如果您可以修改A结构,则可以考虑将这些值添加到A中并使用未初始化的值(使用指针或boost::optional)并将其初始化为懒惰。

否则,如果您无法修改A并且不想将每个A的值复制到相应的B中,您可以考虑B来自A的{​​{1}} ,只需拥有其他属性。然后,您将维护全局std::map<A*, B> [1] ,并通过查看地图来查找其他属性。如果您选择此路径,请问自己是否知道何时从A中删除过时的map

  1. 我使用A*,因为您希望避免复制A

答案 1 :(得分:1)

如果A是属性较少的B,那么它不是B吗?否则,我们可以从世界上的任何对象转换为任何其他对象,只需查找具有相同名称/签名的属性/方法。

但我不得不质疑你为什么要传递一个你知道不是正确类型的对象。如果该方法不需要B提供的额外属性,则将其签名更改为A *而不是B *。如果它确实需要这些值,那么你就无法传入一个没有它们的对象。

如果你真的真的必须这样做,而且我认为你看到我认为它不是一个好的设计,那么或许可以考虑在一个带有A的静态方法,并返回一个带有未知的新B属性设置为null或其他。