7
\$\begingroup\$

I've some classes (Derived1, Derived2, etc.) derived from class Base. All of derived classes have a following methods (reduced sample):

void Derived1::handleTimer(const StatusType &st) {
  if (!st.isOk()) {
    m_timer->WakeUpPeriod(10); // wait for 10 seconds;
    m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
    return;
  }

  try {
    ... // there is some specific for Derived's code
    m_timer->WakeUpPeriod(10 * 60); // wait for 10 minutes;
    m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
  }
  catch(...) {
    m_timer->WakeUpPeriod(10); // wait for 10 second;
    m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
  }
}

void Derived1::start() {
  m_timer->WakeUpPeriod(1); // wait for 1 second;
  m_timer->SetHandler(boost::bind(Derived1::handleTimer, this, _1));
}

I'd like to move these methods to Base. However, my trying looks pretty ugly. Is there more appropriate way? There is my current solution.

class Base {
public:
  typedef boost::function <void (const StatusType&)> HandlerType;
  Base(HandlerType handler) : m_hadler(handler) {}
  void start() {
    m_timer->WakeUpPeriod(1); // wait for 1 second;
    m_timer->SetHandler(m_handler);
  }
protected:
  virtual void doSomeSpecific() = 0;

  void handleTimer(const StatusType &st) {
    if (!st.isOk()) {
      m_timer->WakeUpPeriod(10); // wait for 10 seconds;
      m_timer->SetHandler(m_handler);
      return;
    }

    try {
      doSomeSpecific();
      m_timer->WakeUpPeriod(10 * 60); // wait for 10 minutes;
      m_timer->SetHandler(m_handler);
    }
    catch(...) {
      m_timer->WakeUpPeriod(10); // wait for 10 second;
      m_timer->SetHandler(m_handler);
    }
  }

private:
  HandlerType m_handler;

  ... // other data and function members
};

Now Derived classes

void Derived1::doSomeSpecific() { ... }

Derived1::Derived1() : Base(boost::bind(Derived1::handleTimer, this, _1) {}

void Derived1::handleTimer(const StatusType &st) { Base::handleTimer(st); }
\$\endgroup\$
3
  • 3
    \$\begingroup\$ Why would the derived classes have to override handleTimer()? Couldn't they just inherit it? \$\endgroup\$ Dec 13, 2013 at 8:50
  • \$\begingroup\$ Why do you call AsynWait on Derived1::handleTimer inside Derived1::handleTimer itself? This looks like an endless recursion to me. \$\endgroup\$
    – Andris
    Dec 13, 2013 at 9:50
  • \$\begingroup\$ @Andris - Looks like I obfuscate code trying to make sample. Thank you. See update \$\endgroup\$
    – Loom
    Dec 13, 2013 at 10:08

1 Answer 1

5
\$\begingroup\$

The use of doSomeSpecific inside of handleTimer is remarkably similar to the Template Pattern.

If there is no base implementation of doSomeSpecific you might consider making it private (still virtual so it can be overridden). Unless of course you really want further derived classes to be able to call the doSomeSpecific implementations of their parent classes.

Also, you can consider making handleTimer non-virtual if all derived classes must have the same behavior.

By making doSomeSpecific private, and handleTimer non-virtual, the only point of customization becomes doSomeSpecific, and it becomes an all or nothing point of customization. This can simplify your implementations of your derived classes, because you can trust that they only customize one specific part of your base class.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.