C++ are classes overused and overrated?

Started by
36 comments, last by iMalc 16 years, 8 months ago
Classes can be useful, but let's face it, when a class is implemented it really represents a new type, and how often does a software programme really need a new type? Far better to use the existing STL classes/types and namespaced functions, function templates, and rarely, new classes/types. OK, where maintenance of state in a function is important, then functor-type classes are useful, but these are not really types, they are a more powerful version of a functional programming approach. And where function pointers were used in C, abstract base classes can be used, but again these are not really new types, which is the idea behind the introduction of C++. Class templates represent a powerful extension of classes, but again, these are often non-intuitive and awkward to use until they can be wrapped in a function template that is implicit in its use. Again, we're back to the functional paradigm. Many beginner C++ programmers have a tendency to go overboard with classes and inheritance, where, in the majority of cases, composition is more suitable. A programme with too many types, though, is a monster of a thing to manage and extend, no?
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
Advertisement
Though not an expert, I agree.. I usually do it functionally until I need to do it OO
[ my blog ]
I mostly agree. I believe a balance between inheritance and composition is good.
For example, in my current work, I only have a few new types; and these tend to be class templates, for example 'math::numeric_sequence<>' and 'math::generated_numeric_sequence<>' which: (1) make the application of std::vector<>, std::list<>, and std::deque<> easier, unify their common methods and offer convenience methods for operations on their data. But instead of template specialisation, the methods refer to overloaded function templates that generically use STL algorithms and iterators. From my experience this approach reduces the amount of code needed, encourages code reuse and offers a more multi-purpose application (the function templates are available for many other uses).
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
WOAH. wait. what?
You make it sound like you'd rather write "void Normalize(Vec3 *)" than "Vec3::Normalize()", which is fine, but not an argument against classes.
Besides you keep saying "class/types", well what would you call just about any data in a program?
a type? not a type? Because any game/application is likely going to need TONES of data types for all the data.
So, the question becomes just a sense of style. Do we want functions that operate on our data? or data that is in a class with operations? or a little of both?
Guess I'm just having a hard time seeing what you are bashing.

Inheritance can be used poorly, and I would argue many people don't immediately understand the proper use of it, but
it defiantly makes a program easier to extend than not having it. I honestly couldn't conceive of how to rework
my state-machine to not have states as classes.

A side bash at STL-ism being that it is good for the general case, but not the specific. The EA-STL papers go
over some of the game related issues of using out-of-the-box implementations of STL. And I've read other places
that some console compilers are less robust compared to high end workstation/server compilers
so templates and inlined functions can throw them for a loop as far as getting good optimization.

And then just a personal note, what is easier to work with under the assumption of an intelesense IDE:
Functional approaches where you have to remember "GameUtil? nope was it is MathUtil? nope GraphicsUtil? ok that is was it GraphicsUtil_TransformVecToScreenSpace()"
or a class approach, where you can just to "myVec.(intelesense list) what do i want, TransformVecToScreenSpace()"
(and let me guess, you are going to respond with why is is named 'GraphicsUtil_' well, in a functional regiem, convention would
dictate you prefix functions to avoid conflicts like Update() having to be cat_update(), dog_update(), etc.
and you do NOT break coding conventions in a large group unless you have a really really good reason to because
it causes even more confusion.)

[Edited by - KulSeran on August 15, 2007 3:26:20 AM]
I disagree. You can do things functionally, yes. But then how do you handle member variables? You either pass a struct to the function - in which case you're just emulating classes the C way. You could use globals, but that's horrible and won't let you have two instances of the data.

One perfect example is the "Player" class we use in our game. There's a base player class which handles the common functionality for all players, like following waypoints, collision and so on, and then derived classes like AI players, the "real" player and network players which handle extended functionality.

You could still do that with functions, but it'd be absolutely horrible to do.
Quote:Original post by random_thinker
Many beginner C++ programmers have a tendency to go overboard with classes and inheritance, where, in the majority of cases, composition is more suitable. A programme with too many types, though, is a monster of a thing to manage and extend, no?
I think that depends on whether you come from learning C first (or perhaps even another non-OO language), or whether you started with C++. The former case, IMHO causes people to get stuck in the ways of non-OO. Whereas in the later people could admittedly overuse classes and inheritance. Classes with nothing but getters and setters can be another side-effect of starting out directly with C++.

I don't think classes are overused in general, just maybe by a few rookies[smile]. Classes/structs are essential for RAII, and without them writing correct code is very difficult and error-prone.

PS: Your username is very fitting!
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Quote:and how often does a software programme really need a new type?

When some new functionality is needed.

Quote:Far better to use the existing STL classes/types and namespaced functions, function templates, and rarely, new classes/types.

The exact same argument applies to every language construct. Why use functions when you have std::copy, std::find, etc. Why have global variables when you have std::cout? Why have type aliases when you can use std::string? You have all these to implement other things with them. If you want an XML library you need new types and if you want file system functionality you need new types.

Quote:OK, where maintenance of state in a function is important, then functor-type classes are useful, but these are not really types, they are a more powerful version of a functional programming approach.

A functional approach with state? Most functional code should be referentially transparent.

Quote:And where function pointers were used in C, abstract base classes can be used, but again these are not really new types, which is the idea behind the introduction of C++.

I'm not sure I follow, how can an ABC be used as a function pointer and how are ABCs used without introducing new types?

Quote:Class templates represent a powerful extension of classes, but again, these are often non-intuitive and awkward to use until they can be wrapped in a function template that is implicit in its use.

Why are they awkward to use? IMO templates is a very intuitive concept once you're familiar with it.

Quote:Again, we're back to the functional paradigm.

How does that lead us to functional programming.

Quote:Many beginner C++ programmers have a tendency to go overboard with classes and inheritance, where, in the majority of cases, composition is more suitable. A programme with too many types, though, is a monster of a thing to manage and extend, no?

No. A decent OO program makes sure to reduce coupling to a minimum so it doesn't become harder to manage or extend. A lot of small types with their own distinct responsibility will allow you to maximize extensibility. Together with some policy-based programming you can attain extensibility and manageability much larger than what can easily be done in a procedural or functional programming.

Quote:I usually do it functionally until I need to do it OO

Functionally? Sure you don't mean procedurally?

Surely there is nothing wrong with procedural or functional programming, but neither is there with OO programming.
What I'm thinking, guys, is that the early ideas of C++ and other OO languages was that hierarchies of class types were the way to go. But hierarchies are, by nature, rigid structures, no? However, blending OO with a more functional approach leads to an organic structure, that can change/be changed much more easily. As for templates, function templates offer the ability to wrap class templates very very conveniently.

I agree that the class/inheritance model does have its place, but use them too much and you'll soon find that, as your programme grows, you will have to make a fundamental re-write of the code. Watch out for those rigid hierarchies.

KulSeran...I would like to be able to write both "void Normalize(Vec3 *)" and "Vec3::Normalize()". That is the way to design, when it is needed, as in my previous example. It really does not take more code when using templates, because the need for specialisation of classes can be reduced. That way one can, in future, re-use code extensively.

Evil Steve...As for member variables, give a small example, let's see what disadvantage there is...
--random_thinkerAs Albert Einstein said: 'Imagination is more important than knowledge'. Of course, he also said: 'If I had only known, I would have been a locksmith'.
Quote:Original post by random_thinker
What I'm thinking, guys, is that the early ideas of C++ and other OO languages was that hierarchies of class types were the way to go. But hierarchies are, by nature, rigid structures, no?
True, and this inheritance-heavy approach to design rapidly creates a large mess. People who know what they're doing tend to avoid these deep types of hierarchies.
Quote:However, blending OO with a more functional approach leads to an organic structure, that can change/be changed much more easily. As for templates, function templates offer the ability to wrap class templates very very conveniently.
I don't know what you call conveniently, but compared to proper functional languages, expressing any sort of functional construct in C++ is a horrible mess. The template and macro voodoo doesn't make it nice, it just makes it possible. It's an unfortunate reality we have to deal with in writing C++ code, though.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

This topic is closed to new replies.

Advertisement