Home > C++, Dev > static_cast for inherited customization

static_cast for inherited customization

Traditionally, virtual is used for a class that can be customized partially. Let’s work with the following design.

class Base {
public:
    void action() {
        puts("action");
        customized();
    }

protected:
    virtual void customized() {
        puts("no customization");
    }
};

When the class is used with MyApp.

class MyApp : public Base {
protected:
    virtual void customized() {
        puts("customized by my app");
    }
};

This use of virtual is perfect from design perspective, although the class Base is not designed as an interface. The only problem is that calling the method customized() cannot be optimized as inline. Well, this is not a problem when customized() is only called once in the method action(). But what if it’s going to be called many times with a trivial implementation? The jump call could simply waste lots of CPU power.

One approach to solve the problem is to use a function object as an argument. Note that it should not be something taking address of a function address like std::mem_fun.

class Base {
public:
    template <typename T>
    void action(T customized) {
        puts("action");
        customized();
    }
};

This change brings a little bit trouble when we just want the inherited class to implement the method customized(). Since when a function object is bound to the method, the method is then on-the-fly to generate new code depending on the customization. If the class Base is not actually an interface, it should not be a problem to bind the whole thing to it’s application customization.

Here goes the final design.

template <typename T>
class Base {
public:
    void action() {
        puts("action");
        static_cast<T *>(this)->customized();
    }

    void customized() {
        puts("no customization");
    }
};

The new code driving the class Base.

class MyApp : public Base<MyApp> {
public:
    void customized() {
        puts("customized by my app");
    }
};

It’s a rule of static_cast playing some magic here. It has a strong guarantee that an object pointer of class/struct being cast to a pointer of new type must have inheritance relationship. The following code will fail to compile when action() is called if class MyApp1 is not inherited from class MyApp, so we are going to make neither wrong use of library classes nor typo mistakes.

class MyApp : public Base<MyApp1> {
// ...
};
Advertisements
Categories: C++, Dev
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: