It's more portable because it will work in all languages, many compatible languages do not support multiple inheritance.
It's more flexible because you get to determine what components go into which "type" at runtime, and you can mix and match components rather than needing to explicitly define every type in code.
Also, you don't need to virtualize your vector that's holding the gui_elements, which means you can have references / concrete types instead of needing pointers everywhere in your client code.
If you think it's more complex then you should actually write out the code that you would need in the multiple inheritance / polymorphics type case. It's a lot, lot, lot more complex.
e.g. say your base type is gui_element, then you inherit from three different interfaces to get the virtuals:
class gui_draw
{
virtual void draw() {};
}
class gui_update
{
virtual void update() {};
}
class gui_input
{
virtual void input() {};
}
Now, you also have a "gui_element" base class:
class gui_element
{
}
and your concrete element inherits from all of those:
class gui_button: public gui_element, public gui_draw, public gui_update, public gui_input
{
// override each of the virtual functions here
void draw() { // my draw };
void update() { // my update };
void logic() { // my logic };
}
then, since you want to store different types of gui_element inside a data structure you need to define a vector of gui_element pointers:
vector<gui_element*> elements;
now, since they're [i]pointers[/i] you have to use new and delete whenever you add a new element:
gui_element *g = new gui_button;
elements.push_back(g);
Compare that to doing the same thing with components:
gui_element is the cocrete class of all ui elements:
class gui_element
{
gui_component *m_draw;
gui_component *m_input;
gui_component *m_update;
void draw()
{
if(m_draw) m_draw->process(this);
}
void update()
{
if(m_update) m_update->process(this);
}
void logic()
{
if(m_logic) m_logic->process(this);
}
// etc
}
vector<gui_elements> elements;
elements.push_back(gui_element(/*params*/)); // notice we didn't need a pointer here
class gui_component // only one base class needed for components
{
virtual void process(gui_element *parent) = 0;
}
class gui_draw_button : public gui_component // wrapper for "draw button" functionality
{
void process(gui_element *parent) { /* do the drawing */ };
} draw_button;
// etc
Now you can make gui_elements by making a constructor which takes three components:
gui_element:: gui_element(gui_component *a, gui_component *b, gui_component *c)
{
m_draw = a;
m_input = b;
m_logic = c;
}
Which allows you to basically concoct variant types much faster than needing to make them all explicitly inherited types from a base class.
Plus, you don't need to refer to [b]all[/b] gui_elements by pointers now and can use references.