4

I just discovered from this Q/A that structs are inheritable in C++ but, is it a good practice, or is it preferable to use classes? In which cases is preferable and in which ones is not?

I have never needed this, but now I have a bunch of messages of different types, but same longitude. I got them in binary in a char array, and I just copy them with memcpy to the struct to fill its fields (I don't know if it is even possible to do it with std::copy).

I guess it would be great to be able to inherit every struct from a base struct with common headers, that is why I searched for this. So a second question would be: if I do this with classes, is it possible to do a memcpy (or std:copy) from a buffer to a class?

Community
  • 1
  • 1
Roman Rdgz
  • 12,836
  • 41
  • 131
  • 207
  • 2
    In C++ structures and classes are almost the same, the only difference being that for `struct` the default visibility is `public` while for classes it's `private`. – Some programmer dude Oct 23 '12 at 07:10
  • 1
    What do you plan to put in the base struct? – Eric Z Oct 23 '12 at 07:15
  • 2
    There is one more difference between `class` and `struct`, which affects inheritance specifically: The default mode of inheritance is `private` with `class`, but `public` with `struct`. So when you do `struct D : A`, this will be the same as `struct D : public A`. But that should not stop you from using inheritance with `struct` of course. – jogojapan Oct 23 '12 at 07:21

2 Answers2

5

Whether you can use a bitwise copy or not has nothing to do with the struct or class tag and only depends on whether said struct or class is_trivially_copiable. Whether they are is defined in the Standard (9/6 [class]) and it basically boils down to not having to declare any other special member methods than constructors.

The bitwise copy is then allowed by the Standard in 3.9/2 [basic.types]

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes (1.7) making up the object can be copied into an array of char or unsigned char. If the content of the array of char or unsigned char is copied back into the object, the object shall subsequently hold its original value. [ Example:

#define N sizeof(T)
char buf[N];
T obj; // obj initialized to its original value
std::memcpy(buf, &obj, N); // between these two calls to std::memcpy,
                           // `obj` might be modified
std::memcpy(&obj, buf, N); // at this point, each subobject of `obj`
                           // of scalar type holds its original value

—end example ]

Note: a bitwise copy of padding bytes will lead to reports in Valgrind.

Using std::copy to the same effect:

char const* b = reinterpret_cast<char const*>(&obj);
std::copy(b, b + N, buf);
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • Ok, so it is possible to do it with classes. Are padding bytes the reason of using #pragma pack? And one more question: could you edit your answer and add the same code using std:copy? I know compiler will most likely change if back to memcpy, but I'm curious about how to call std:copy for this task – Roman Rdgz Oct 23 '12 at 09:00
  • 1
    @RomanRdgz: `#pragma pack` will indeed remove padding bytes (well `pack(1)` will, `pack(2)` may not) at the cost of *correctness*. However, padding bytes are introduced to respect alignment constraints on the types, so removing them equates to violating those constraints. On x86, the code will work, but access to the mis-aligned parts will be slower (the CPU does extra work); on some architectures, a hardware exception may be raised (crashing the program). **Do not use it.** – Matthieu M. Oct 23 '12 at 09:38
  • Ok I see, so with a pointer to the class it is possible to use std::copy. Thanks – Roman Rdgz Oct 23 '12 at 10:49
  • About the pack, the problem is that my buffer contains n bits representing something, the following m bits represent another thing... I need bit level when copying to the struct, so I need to pack. If I can't use (or shouldn't) that pragma, how would you suggest doing it? – Roman Rdgz Oct 23 '12 at 10:51
  • 1
    @RomanRdgz: Two options. The portable and evolutive one is to create a routine that read from the `char` array and set each field of the structure appropriately (and back). This is typically called **serialization**. The optimized one, which is highly-platform dependent and require a new structure for each new version of the protocol, is to use **bit fields**. – Matthieu M. Oct 23 '12 at 11:01
1

The only difference between struct and class is the default access modifier to its members. In struct it's public and in class it's private (until stated otherwise). Besides that struct and class are identical in C++. Sometimes structs are prefered for PDO (Plain Data Objects) over classes for readability but that's really up to a coding convention.

SomeWittyUsername
  • 18,025
  • 3
  • 42
  • 85