I\'ve started coding in C++, coming from a Java background (actually I\'d studied C++ at my university, but we never got to the STL etc.)
Anyway, I\'ve gotten to the
You need to try and let go of the Java mindset. You see, the beauty of STL, is that it separates algorithms from containers through iterators.
Long story short: Pass around iterators to your algorithms. Don't inherit.
Here are all the containers: http://en.cppreference.com/w/cpp/container
And here are all the algorithms: http://en.cppreference.com/w/cpp/algorithm
There may be two reasons why you may want to inherit:
To briefly touch upon the first point, if you need to store an array of things (say an array of objects in a game scene), do exactly that, have an array of these objects as a member to the Scene object. There is no need to subclass to fully utilize the container. In other words, prefer composition over inheritance. This has been done to death already, and is accepted in the Java world as doing "The Right Thing". See discussion here, it's in the GoF book! Same thing applies to C++.
Example:
To address the second point let's consider a scenario. You are making a 2D sidescroller game, and you have a Scene object, with an array of GameObjects. These GameObjects have positions, and you'd like to sort them by position, and do binary search to find the closest object, as an example.
In the C++ mindset, the storage of elements and manipulation of containers are two separate things. The container classes provide the bare minimum functionality, for creation/insertion/removal. Anything interesting above that is relegated to Algorithms. And the bridge between them are iterators. The idea is that whether you use std::vector (equivalent to Java's ArrayList I think), or your own implementation is irrelevant as long as access to elements is the same. Here is a contrived example:
struct GameObject {
float x, y;
// compare just by x position
operator < (GameObject const& other)
{
return x < other.x;
}
};
void example() {
std::vector objects = {
GameObject{8, 2},
GameObject{4, 3},
GameObject{6, 1}
};
std::sort(std::begin(objects), std::end(objects));
auto nearestObject = std::lower_bound(std::begin(objects), std::end(objects), GameObject{5, 12});
// nearestObject should be pointing to GameObject{4,3};
}
Things to note here, the fact that I used std::vector to store my objects, doesn't matter as much as the fact I can perform random access on its elements. The iterators returned by the vector capture that. As a result we can sort and perform binary search.
The essence of the vector is random access to elements
We can swap out the vector for any other random access structure, without inheritance, and the code still works perfectly fine:
void example() {
// using a raw array this time.
GameObject objects[] = {
GameObject{8, 2},
GameObject{4, 3},
GameObject{6, 1}
};
std::sort(std::begin(objects), std::end(objects));
auto nearestObject = std::lower_bound(std::begin(objects), std::end(objects), GameObject{5, 12});
// nearestObject should be pointing to GameObject{4,3};
}
For reference, see the functions I have used:
Why is this a valid alternative to inheritance?
This approach gives two orthogonal directions for extensibility: