1

I guess this a classic, but in my case I have constraints that should simplify the problem.

It's just that I'm getting some struct A at the input of my module, and want to add a few attributes to it. So I create a struct B which extends A, and add what I need.

Now whenever I call a method that expects a B but I feed it an A, the compiler ain't happy : A objects may not be Bs, like all felines are not lions.

But in my case, I swear that all As are Bs, albeit with less attributes. Attributes that are not found can be reported as uninitialized, that's fine, I also swear I will never call an attribute before initializing it. Basically, first thing I do when getting A objects as input is to fill the remaining B attributes, which are calculated based on A attributes. I just don't want to make copies of the As I get into Bs just to add a few attributes, because then the attributes of the As would be copied in memory. I'm not gonna ever modifiy those original attributes of A either, I'm just gonna use them to calculate derived attributes, and then pass around and work on B objects with A attributes and derived attributes.

Example :

From common, project-wide header :

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

From local header :

struct LocalRectangle : Rectangle {
    int area;
}

void updateModule(Rectangle inputRect);

From local source :

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

How do I do this ?

Thanks in advance,

Charles

Charles
  • 988
  • 1
  • 11
  • 28
  • Can you please post code? – Jossie Calderon Jul 21 '16 at 09:02
  • Maybe you could add a field to As struct of type `std::map`, which would hold the different attributes, and remove the Bs structs, being everything of type A. – LoPiTaL Jul 21 '16 at 09:02
  • Can you modify `A`? – Motti Jul 21 '16 at 09:07
  • std::map sounds more complicated (and resource-greedy) than necessary. I can't modify A, other people down the line will use them. I don't need to anyway. – Charles Jul 21 '16 at 09:15
  • Note that in your example you're passing `Rectangle` by value so you're copying it anyway. In this case you might as well copy into `LocalRectangle`. – Motti Jul 21 '16 at 09:21

2 Answers2

1

If you can modify the A struct you can consider just adding these values into A with an uninitialised value (using a pointer or boost::optional) and initialise them lazily.

Otherwise if you can't modify A and don't want to copy the values from each A into it's corresponding B you can consider having B not derive from A, just have the additional attributes. Then you'll maintain a global std::map<A*, B>[1] and find the additional attributes by looking in the map. If you choose this path ask yourself whether you know when to remove obsolete As from the map.


  1. I'm using A* since you want to avoid copying As.
Motti
  • 110,860
  • 49
  • 189
  • 262
1

If A is a B with a few less attributes then it's not a B is it? Otherwise we'd be able to cast from any object in the world to any other object, and just look for attributes/methods that have the same names/signatures.

But I'd have to question why you would want to pass in an object that you know is not of the correct type. If the method doesn't need the extra attributes provided by B then change its signature to take A* rather than B*. And if it does need those values then you can't pass in an object that doesn't have them.

If you really really really must do this, and I think you see that I don't see it is a good design, then perhaps consider making a static method somewhere that takes an A, and returns a new B with the unknown attributes set to null or something.

LordWilmore
  • 2,829
  • 2
  • 25
  • 30