开发者

C++: Using one type as another

I'm using the Chipmunk physics engine for my C++ project.

Chipmunk has it's own vector, cpVect, which is nothing but a struct { d开发者_开发百科ouble x, y; };

However I have my own operator overloaded Vector class in my project - and I'd like to use it just as a cpVect and vice-versa, without any conversions (my class Vector's only data fields are double x, y as well)

Currently I use this for implicit conversions (for argument passing, setting a Vector variable to a cpVect, etc.)

inline operator cpVect() { return cpv( x, y ); };
inline Vector( cpVect v ) : x( v.x ), y( v.y ) {}

This works for most things, but has a few problems - for example it isn't compatible for using arrays of the type Vector with cpVect arrays.

For that I currently have to do this:

Vector arrayA[123];
cpVect* arrayB = (cpVect*) arrayA;
  • Is it possible by some way to use my Vector as cpVect and vice-versa? Data is identical with both structures, mine only has additional methods.


So if I understand you, you have this:

class Foo
{
  double x, y;
};

class Bar
{
  double x, y;
};

...and you want pretened that a Foo is actually a Bar, right?

You can't -- not without evoking Undefined Behavior. No matter what you try, you will fall in to the great UB black hole.

  • if you try to use a union, you'll evoke UB when you assign to my_union.foo and read from my_union.bar
  • if you try to reinterpret_cast you'll evoke UB when to try to use the casted pointer
  • if you try to use a C-style cast, you'll have the same problems as above

The problem is this: Even though Foo and Bar look the same, they are not the same. As far as C++ is concerned, they are completely different types, totally unrelated to each other. This is a Good Thing, but it can also throw up some barriers that can seem to be artificial and arbitrary.

So, in order to do this without evoking UB, you need to convert. You could make this nearly automatic, by simply adding a couple facilities to Bar (which I presume to be the one you wrote, not the one from the library):

class Bar
{
public:
  Bar(const Foo& foo) : x(foo.x), y(foo.y) {}; // lets you convert from Foo to Bar
  Bar& operator=(const Foo& foo) { x = foo.x; y = foo.y; return * this; }

  operator Foo() const { Foo ret;  ret.x = x; ret.y = y; return ret; } // lets you convert ffrom Bar to Foo
private: 
  double x, y;
};

Which will let you go from Foo to Bar and back again with little or no code. Plus the compiler will optimize a lot of this away in release builds.


If both of those are simple PODs (no virtual functions etc), then a simple reinterpret_cast could save you here.


Derive yours from theirs and fix-up the problems? Seems simple enough to have 1000 traps. :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜