Design question

Started by
13 comments, last by Servant of the Lord 11 years, 6 months ago
Yep. smile.png

However, "Drawable" sounds like an abstract base class used in inheritance.
If it is a base class, for polymorphism to work you have to use either pointers or references. So your list would be List<Drawable*>, and you'd need to use new and delete to manage the dynamic memory, or preferably: List<some_smart_ptr<Drawable>> to not have to worry about the memory AND enable polymorphism.

If it isn't an abstract base class, a better name would be "Item" (I'm assuming it's an item, since your list says 'items'). If it's not an item, perhaps "Object" or "GameObject" would make more sense.

Another hint, unrelated to the current topic:
When iterating over an array, and if you're confident that you are staying within 0 to size-1, you can use items[index] instead of items.at(index). The at() function checks bounds (but you already know you are within bounds) and throws an exception if you are out of bounds. The subscript [] operator doesn't do any bounds checking, and so has unpredictable results when you go out of bounds, but is faster when iterating over a container since you already know you are within bounds.
([size=2]And if you are using C++11, there's an even better way which I won't get into here)
Advertisement
This was just an example i could think off of the top of my head.

I actually forgot that you can do that for lists and vectors. Also I would enjoy the C++11 way, incase i do move to that standard.
In C++11 instead of a normal for-loop:
//Normal for-loop with indexing:
for(size_t index = 0; index < container.size(); index++)
{
DoSomething( container[index] );
}

//Normal for-loop with iterators:
for(Container<Type>::iterator it = container.begin();
it != container.end(); it++)
{
DoSomething( *it );
}


First, C++11 includes the keyword 'auto' which greatly reduces the amount of typing, and makes the code cleaner, and makes the code easier to change:
//Normal for-loop with iterators AND using C++11 'auto' keyword:
for(auto it = container.begin(); it != container.end(); it++)
{
DoSomething( *it );
}

Or (with std::begin() and std::end() also working for non-container arrays):
for(auto it = std::begin(container); it != std::end(container); it++)
{
DoSomething( *it );
}


Second, C++11 also introduces a new version of for() loop for when you know you are iterating from begin() to end() without change, and this further reduces the amount of typing, nicely avoids any (visible) iterator dereferencing, and guarantees to the compiler (and anyone reading the code) that you aren't altering the iterator within the for() loop.

This new for-loop we call 'range-for', and it looks like this:
for(const auto &element : container)
{
DoSomething( element );
}


So in your example:
some_kind_of_container< some_kind_of_smart_ptr<Drawable> > items;

for(const auto &item : items)
{
item->draw();
}
The range-for loop looks like a for-each loop. Would that be correct?
Yes, exactly. Except C++ doesn't have a for-each loop. Microsoft had it as a non-standard extension in Visual Studio that wasn't portable.
for-range is standard C++, and every compiler that claims to support C++ must support it from now on.

Visual Studio had "for each()", Boost had FOR_EACH() macro, Qt had foreach() macro. Now we have a single consistent and properly portable for-each. "for(element-type : container)"

This topic is closed to new replies.

Advertisement