Safety of casting between pointers of two identical classes?
Let's say I have two different classes, both represent 2D coordinate data in the same internal way like the following:
class LibA_Vertex{
public:
// ... constructors and various methods, operator overloads
float x, y
};
class LibB_Vertex{
public:
// ... same usage and internal data as LibA, but with different methods
float x, y
};
void foobar(){
LibA_Vertex * verticesA = new LibA_Vertex[1000];
verticesA[50].y = 9;
LibB_Vertex * verticesB = reinterpret_cast<LibB_Vertex*>( vertexA );
print(verticesB[50].y); // should output a "9"
};
Given the two classes being identical and the function above, can I reliably count on this pointer conversion working as expected in every case?
(The background, is that I ne开发者_开发技巧ed an easy way of trading vertex arrays between two separate libraries that have identical Vertex classes, and I want to avoid needlessly copying arrays).
C++11 added a concept called layout-compatible which applies here.
Two standard-layout struct (Clause 9) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types (3.9).
where
A standard-layout class is a class that:
- has no non-static data members of type non-standard-layout class (or array of such types) or reference,
- has no virtual functions (10.3) and no virtual base classes (10.1),
- has the same access control (Clause 11) for all non-static data members,
- has no non-standard-layout base classes,
- either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
- has no base classes of the same type as the first non-static data member.
A standard-layout struct is a standard-layout class defined with the class-key
struct
or the class-keyclass
.A standard-layout union is a standard-layout class defined with the class-key
union
.
Finally
Pointers to cv-qualified and cv-unqualified versions (3.9.3) of layout-compatible types shall have the same value representation and alignment requirements (3.11).
Which guarantees that reinterpret_cast
can turn a pointer to one type into a pointer to any layout-compatible type.
I would wrap that conversion up in a class (so that if you need to change platform or something, it's at least localised in one spot) but yes it should be possible.
You'll want to use reinterpret_cast
, not static_cast
as well.
Theoretically this is an undefined behavior. However, it may work in certain systems/platforms.
I would suggest that you should try to merge 2 classes into 1. i.e.
class Lib_Vertex{
// data (which is exactly same for both classes)
public:
// methods for LibA_Vertex
// methods for LibB_Vertex
};
Adding methods into a class
will not affect its size. You may have to change your design a bit but it's worth it.
Technically this is undefined behavior. In reality, if the same compiler was used to compile both classes, they'll have the same layout in memory if the fields are declared in the same order, have the same types and the same access level.
精彩评论