tags:

views:

3873

answers:

7

If I have a class as follows

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

And a struct as follows

struct
{
   int x;
   int y;
} example_struct;

Is the structure in memory of the example_struct simmilar to that in Example_Class

for example if I do the following

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

will foo_struct.x = 8 and foo_struct.y = 9 (ie: the same values as the x,y values in the foo_class) ?

The reason I ask is I have a C++ library (don't want to change it) that is sharing an object with C code and I want to use a struct to represent the object coming from the C++ library. I'm only interested in the attributes of the object.

I know the ideal situation would be to have Example_class wrap arround a common structure between the C and C++ code but it is not going to be easy to change the C++ library in use.

+8  A: 

Is the structure in memory of the example_struct simmilar to that in Example_Class

The behaviour isn't guaranteed, and is compiler-dependent.

Having said that, the answer is "yes, on my machine", provided that the Example_Class contains no virtual method (and doesn't inherit from a base class).

ChrisW
I know I probably shouldn't make my solution depend on architecture but what machine/compiler are you using?
hhafez
Microsoft's compiler.
ChrisW
+6  A: 

In the case you describe, the answer is "probably yes". However, if the class has any virtual functions (including virtual destructor, which could be inherited from a base class), or uses multiple inheritance then the class layout may be different.

Greg Hewgill
+1  A: 

To add to what other people have said (eg: compiler-specific, will likely work as long as you don't have virtual functions):

I would highly suggest a static assert (compile-time check) that the sizeof(Example_class) == sizeof(example_struct) if you are doing this. See BOOST_STATIC_ASSERT, or the equivalent compiler-specific or custom construction. This is a good first-line of defense if someone (or something, such as a compiler change) modifies the class to invalidate the match. If you want extra checking, you can also runtime check that the offsets to the members are the same, which (together with the static size assert) will guarantee correctness.

Nick
A: 

Classes & structs in C++ are the equivalent, except that all members of a struct are public by default (class members are private by default). This ensures that compiling legacy C code in a C++ compiler will work as expected.

There is nothing stopping you from using all the fancy C++ features in a struct:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};
Mike Thompson
I thought this equivalence only meant that you can compile C code as C++ code
They're "equivalent" in some way, but I doubt (though I don't know) whether the standard says that their in-memory layouts are identical; also, having a 'virtual'method (as in your flawed example) **will** likely change the layout (by adding a vptr to each instance).
ChrisW
All common compilers place the vtable pointer at the start of the object, so having a virtual method **will** alter the memory layout of the class. C++ guarantees identical behaviour only for POD ("Plain Old Data") types: a struct or class must obey several restrictions to classify as POD.
j_random_hacker
Removed my earlier comment because thinking it over, POD classes are by definition interchangeable with C structs.
Max Lybbert
+15  A: 

The C++ standard guarantees that memory layouts of a C struct and a C++ class (or struct -- same thing) will be identical, provided that the C++ class/struct fits the criteria of being POD ("Plain Old Data"). So what does POD mean?

A class or struct is POD if:

  • All data members are public and themselves POD or fundamental types (but not reference or pointer-to-member types), or arrays of such
  • It has no user-defined constructors, assignment operators or destructors
  • It has no virtual functions
  • It has no base classes

About the only "C++-isms" allowed are non-virtual member functions, static members and member functions.

Since your class has both a constructor and a destructor, it is formally speaking not of POD type, so the guarantee does not hold. (Although, as others have mentioned, in practice the two layouts are likely to be identical on any compiler that you try, so long as there are no virtual functions).

See section [26.7] of the C++ FAQ Lite for more details.

j_random_hacker
A: 

Why not explicitly assign the class's members to the struct's when you want to pass the data to C? That way you know your code will work anywhere.

Chuck
A: 

You probably just derive the class from the struct, either publicly or privately. Then casting it would resolve correctly in the C++ code.

Daemin