views:

1235

answers:

3

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 to move between the two?

+9  A: 

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.

Alex B
Thanks for that. I was pretty sure it was ok, but had never actually seen it done in practice.
Shane MacLaughlin
+4  A: 

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.

Johannes Schaub - litb
+1  A: 

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.

Stephen C. Steel