0

Sutter and Alexandrescu have discribed in a quite simple and self contained way the ecosystem of C++ classes, providing 6 main categories

  1. Value classes (e.g., std::pair, std::vector)
  2. Base classes (building blocks of class hierarchies)
  3. Traits classes (templates that carry information about types)
  4. Policy classes (fragments of pluggable behavior)
  5. Exception classes
  6. Ancillary classes that typically support specific idioms (e.g. RAII)

It is a very handy shortcut when taking decisions on class design and I' ve used it before, but there are two things that come into play: 2004 (the year that book was puplished) is a long time ago in software engineering and there is a new language standard since then. I can't but wonder:

  • Is this this categorization still relevant?
  • Are there any new items ammending the above list?
  • Is there an alternative categorization, by authors having matching authoritative power?
  • Is there a standard taxonomy for c++ classes? (for all I know this could also be it)

NOTE:

I hope the 4 questions above have a clear setting. To avoid opinion based answers, a valid answer should link/mention examples, code usage or standard excerpts that verify its statings.

Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153

2 Answers2

1

In a categorization like this I would also include Inner classes as the type of classes that declare containment. For example Engine is included in a Vehicle:

class Vehicle{
    public:
    class Engine{

    };
    Engine* vehicle_engine;
};

But it reduces the readability of the code. I prefer composition over Inner Classes. It is not so easy to distinguish between language featured type of classes and design patterns. For example can Singleton be on that categorization?

Avraam Mavridis
  • 8,698
  • 19
  • 79
  • 133
  • That's a value class. As for `Singleton`, you could implement it both as a value class and as a base class (if using the curiously recurring tepmlate pattern). It is indeed a diffucult task to provide clear boundaries between such concepts, that's why I like the mentioned categorization so much. – Nikos Athanasiou Feb 22 '14 at 10:39
1

The categorisation is relevant in C++11 as well, the basic OOP premises haven't changed. The scope of the answer has to be limited because you explicitly ask about class types, nevertheless, I would add Functors (including lambdas) to the list.

Also now that enums are strongly typed (specified with the enum class keyword), they can arguably have their own place in the pantheon.

mockinterface
  • 14,452
  • 5
  • 28
  • 49
  • 1
    Functors are value classes (since they get passed by copy). They are also policy classes (since they are used as template parameters). I suppose they might get classified as ancillary classes depending how flexible that category needs to be (since they support a specific idiom: callables as template parameters). But that latter category has no particular implications for how the class is implemented, so it's probably unimportant whether or not a given class is considered ancillary. Enums are value types too, and whether it's an important sub-category depends how detailed a taxonomy you want. – Steve Jessop Feb 22 '14 at 11:57
  • Yes functors fall into the **value** class category. But lambdas could be a new category, if we consider the whole notion of closures (I've just posted about this). Closures are a programming concept new to C++. – Nikos Athanasiou Feb 22 '14 at 12:29
  • @NikosAthanasiou I don't really agree that functional behaviour is simply "value classes", but since the question already begins with an appeal to authority, there is little to be said, except to point the readers to one small observation. It's enough to look to the comments to this very answer and see that functors are classified as value/policy/ancillary, and ... wait they can be base classes as well. To my non-authoritative opinion it is clear that function objects or "functions with state" stand on their own, especially if the vague "classes that support RAII" get their own category. – mockinterface Feb 22 '14 at 12:54
  • @NikosAthanasiou Referring to your argument re closures - lambdas are just (an extremely useful syntactic sugar for) functors. Closures are functions that refers to variables in some context, and since they are implemented with lambdas - they are functors as well. Functors are what counts. – mockinterface Feb 22 '14 at 13:04
  • @mockinterface Value classes are defined as those that comply with the requirements : >1.having a public destructor, copy constructor, and assignment with value semantics 2.Having no virtual functions (including the destructor) 3.Intended to be used as a concrete class, not as a base class 4.Usually instantiated on the stack or as a directly held member of another class. – Nikos Athanasiou Feb 22 '14 at 13:24
  • @mockinterface I couldn't provide definitions for all of the items, in case it would be weird copyright-wise(that's why I linked to the book). It seems that functors can comply with the requirements but lambdas most certainly cannot. I deleted my post on closures since lambdas are mentioned here (and it seemed as a restate - you already had my +1). Now that the requirements for value classes are out in the open I hope I'm communicating why the workings of closures (like lambdas) are a new category (IMHO) – Nikos Athanasiou Feb 22 '14 at 13:29
  • @NikosAthanasiou: lambdas satisfy all of 1..4, although if you really want to you can instantiate them other than as temporaries on the stack by assigning to an `auto` variable. I think it's excessive to get too formal about the idea of C++ lambdas as closures. They provide the syntactic sugar of a "proper" closure because you can capture-all with `[&]` or `[=]`, but they don't provide the full functionality of "proper" closures in other languages since they don't extend the lifetime of the stack frame they capture. – Steve Jessop Feb 23 '14 at 11:25
  • @SteveJessop I was mostly based in that _The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non- union class type_ and one has no access to contructor/destructor in unnamed classes. What you say makes sense though, it is debatable, not in SO apparently, the post will be closed, thnx for your help on sorting this out. – Nikos Athanasiou Feb 23 '14 at 11:36
  • @NikosAthanasiou: it does have a public destructor (which is called when the object goes out of scope), copy constructor (used when it's passed by value) and copy assignment (which you don't normally use but is there). Think about what you can do with a lambda type once you've captured it as a template parameter `T`. The reason I gave the quote from Borges is that these classifications rarely end up clean, and he gives an example of a particularly messy one ;-) – Steve Jessop Feb 23 '14 at 11:47
  • @SteveJussop I didn't say it had not, I said 'one has no access' to them (meaning to modify them - ofcourse the scope can access them to create and destroy objects). The extend to which controlling the behaviour of those members is crucial to name a class `value class` is the gap between our views on the point. ( Yes +1 for the quote :P it made sense immediately ) – Nikos Athanasiou Feb 23 '14 at 11:56