The question says it all really. Am I allowed derive a class from a struct, or should I create a class that embeds my struct and defines copy constructors and an = operator
In C++ struct
is (almost) synonymous to a class
(except of different default access level), so yes, you can.
struct A {
// fields are public by default
};
class B: public A {
// fields are private by default
};
I'm not familiar with MFC, but it looks like an attempt to maintain both C and C++ APIs.
Of course you are. What is different regarding the inheritance is that if you define a class, it will inherit private from other classes/structs. If you define a struct and derive it from a class or struct, it will be a public inheritance by default:
// the following two are equivalent except that one time class is
// used and the other time struct
struct f : g { };
class f : public g { };
If you wonder how you should wrap C structs - i would embed them as a member into the class. Because the C structs were not designed to be inherited from (think of the neither protected nor virtual destructor in the C structs - they can't have one). They are simple aggregates that collect data. And putting them as members uses them as such (as in "a point has a pair of an x and an y coordinate").
C structs also expose members that possibly should not be exposed in the class. Containment allows precise control over what is exposed and what not by get/set functions and you can still let it give you a copy or reference to the contained naked C struct object.
Yes. you can derive a class from a struct. In C++, a struct is simply a class where the default access is public rather than private. Deriving a class from a struct that only adds non-virual member functions and/or static functions is a useful technique to provide a C++ interface while maintaining compatability with a C style API.
This is exactly the approach used by MFC for many of the C structs (contrary to what you state in your question).
For example, the CRect class is publicly derived from struct tagRECT (the more commonly used name RECT is a typededf for struct tagRECT). Because struct tagRECT defines all the data members, and CRect adds only non-virtual member functions, the memory layout of CRects and RECTs are identical - you can use a CRect as an argument for any function expected a RECT and vice-versa.