[C++] Design question? (Polymorphism)

Started by
5 comments, last by Waaayoff 13 years, 7 months ago
I'm creating a GUI, and in my code, i have an abstract Control class. All controls (Panels, Buttons, Sliders etc..) derive from this class. Now the problem is that other than all the common data, different controls require different data.

So for example a Panel requires a data member m_Visible. The other controls do not need this member. Since i'm using polymorphism, i can't access functions of the derived class, so i have to have a virtual function in the base class that interacts with the m_Visible member:

virtual bool IsVisible() { return m_Visible; } 


The problem however is that now i have to add a default functionality for this function since i have other derived classes that have no implementation of this function.. And since i have to return a value, i do this:

bool IsVisible() { throw(exception_here); }


Is this a bad idea or is it acceptable in my situation?

"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "
Advertisement
This is poor design, usually only acceptable when you need to fit an existing hierarchy and you know the method won't be called. In your case, if you know it can be called then you have enough type information to do a direct cast. If not, you risk calling this fake function which throws an exception.

In your case, the virtual base function can be implemented like so:
virtual bool IsVisible() { return true; }

Remember, a member function isn't special, it doesn't have to return a member.
I think you should rethink your design.

Generally, your IsVisible should be implemented in your Control class; why only put a working IsVisible in the Panel? A Button also can be either 'visible' or 'not visible'. If it's always supposed to be visible then just return true there.
Quote:Original post by Waaayoff
I'm creating a GUI, and in my code, i have an abstract Control class. All controls (Panels, Buttons, Sliders etc..) derive from this class.


So what is in common between Controls that they need to be related like this?

Quote:Since i'm using polymorphism, i can't access functions of the derived class


You only lose access to these functions when you deliberately "forget" the type, by, e.g. putting the Controls in a container of Controls. I.e., actually "using" polymorphism.

I think something is confused in your design: either a given bit of code cares that a particular Control is a Panel, or it does not. If it does, it should not be trying to treat the Panel polymorphically. If it does not, it should not need access to Panel-specific information.

Quote:so i have to have a virtual function in the base class that interacts with the m_Visible member


Well... I can certainly see why you'd need some kind of code that interacts with it (otherwise it's just taking up space); but do you really need an accessor? What is the outside calling code going to do with the information about whether a Panel is visible or not? Why isn't the Panel doing something with that information instead (e.g. conditionally bailing out of its rendering)?

Quote:The problem however is that now i have to add a default functionality for this function


Well... that should be the least of your problems here. Are the other components visible or aren't they? This doesn't seem like it ought to be a hard question to answer.

But the point is, you need to think more about your design.
Okay. Here's the design:

I have a GUI class, the mothership. This takes care of everything, handling input, rendering, creating controls etc..

Now, this class has a list of Parent Panels. And every panel has a list of children controls that reside inside it.

In the GUI class i have a list of vertices that i send to the vertex buffer. I fill it by looping through all the parent panels, if the panel is visible, i add it's vertices to the list. Since the parent is visible, then so must be it's children so i loop through them and add their vertices to the list.. And so on..

I use polymorphism so i can have access to all my controls from the GUI class and Parent Controls using a vector of pointers..
"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "
class UIElement {  virtual void render(RenderList * list) = 0;};class Child : UIElement {  virtual void render(RenderList * list) {    // something  }};class Parent : UIElement {  virtual void render(RenderList * list) {    if (!visible) return;    list->add(this);    for (int i = 0; i < children.size(); i++) {      children->render(list);    }  }private:  boolean visible;  vector<UIElement> children;};class GUI {  void render() {    RenderList * r = new RenderList();    root->render(r);    for (int i = 0; i < r.size(); i++) {      // actually display everything in r    }  }private:  UIElement * root;};
Okay i think i understand what you mean..

I removed all the getters and instead of having the GUI class take care of everything, i changed my code such that it's more of a coordinator. Now the Controls take care of rendering and updating themselves.
"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "

This topic is closed to new replies.

Advertisement