Yana D. Nugraha
Yana D. Nugraha

Reputation: 5309

Avoiding many typecasting

I'm creating a UI system for my OpenGL application and I have this design...

The UI manager:

class UIManager {
public:
  UIElement *add(UIElement *element);
}

Example element:

class Button : public UIElement {
public:
  Button(UIElement *parent, const string &caption, const Point &position);
}

Now everytime I want to instantiate a button and keep the pointer to it, I'll have to write this:

// somewhere in the header file
UIManager *manager;
Button *button1, *button2;

// in cpp
button1 = static_cast<Button *>(manager->add(new Button(0, "Enter", Point(10, 10))));
button2 = static_cast<Button *>(manager->add(new Button(0, "Exit", Point(10, 50))));

which looks a bit lengthy to me, especially when I have a dozen of elements.

Is this a bad design? Is there another way to get over this?

Upvotes: 0

Views: 116

Answers (3)

Alex Brown
Alex Brown

Reputation: 42942

You can assign the buttons to the variables inside the argument to add:

// somewhere in the header file
UIManager *manager;
Button *button1, button2;

manager->add(button1 = new Button(0, "Enter", Point(10, 10)));
manager->add(button2 = new Button(0, "Exit", Point(10, 50)));

Also remove the returned argument from the add method.

Upvotes: 2

juanchopanza
juanchopanza

Reputation: 227618

You can declate add as a template method, and avoid all casting:

class UIManager {
public:
    template<typename T> 
    T* add(T *element) {
      // do something with element
      return element;
    }
}

Then your client code becomes

button1 = manager->add(new Button(0, "Enter", Point(10, 10)));

Upvotes: 2

ecatmur
ecatmur

Reputation: 157504

Declare the add method as a method template forwarding to the actual method:

class UIManager {
public:
    UIElement *add(UIElement *element);
    template<typename T> T *add(T *element) {
        return static_cast<T *>(add(static_cast<UIElement *>(element))); }
}

Button *button1 = manager->add(new Button(0, "Enter", Point(10, 10)));

Note that instead of raw pointers you should be using managed pointers (unique_ptr or, in this case, shared_ptr).

Upvotes: 0

Related Questions