Skip to main content

Item 19: Treat class design as type design

Concept

Designing good classes is challenging because designing good types is challenging. You should approach class design with the same care that language designers lavish on built-in types. Before defining a new type, you should consider a set of design questions that guide virtually every aspect of your type: creation/destruction, initialization vs. assignment, pass-by-value semantics, legal values, inheritance, conversions, operators, access control, and generality (should it be a template?).

Code Example

// Questions to answer when designing a new type:

// 1. How should objects be created and destroyed?
// -> constructors, destructors, memory allocation

// 2. How should initialization differ from assignment?
// -> constructor vs. operator= behavior

// 3. What does pass-by-value mean for your type?
// -> copy constructor defines this

// 4. What are the legal values?
// -> invariants, error checking in member functions

// 5. Does your type fit into an inheritance graph?
// -> virtual/non-virtual functions, virtual destructor?

// 6. What conversions are allowed?
// -> implicit/explicit constructors, conversion operators

// 7. What operators and functions make sense?
// -> member vs. non-member

// 8. What standard functions should be disallowed?
// -> declare = delete

// 9. Who should have access to members?
// -> public, private, protected, friend

// 10. What guarantees does your type offer?
// -> exception safety, thread safety, performance

// 11. How general is your type?
// -> perhaps a class template instead

// 12. Is a new type really needed?
// -> maybe a non-member function or template will do

class Widget {
// Each design decision above shapes this class
};

Full source code

Things to Remember

  • Class design is type design. Before defining a new type, be sure to consider all the issues discussed in this Item.
  • The quality of your types determines the quality of your code.
  • Item 18 — Making interfaces easy to use correctly
  • Item 20 — Pass-by-reference-to-const vs pass-by-value
  • Item 22 — Declaring data members private
  • Item 24 — Non-member functions for type conversions