Virtual function style

C++ is very powerful language. I have liked it from its early days. When it is properly used, it relieves lots of coding inconvenience and provide good modularity.
However, it can give you lots of headache if its powerful features are used to show the author’s capability too much. I don’t think good programmer is the one who uses language features in tricky way or who has showy-attitude.

Back in 90s, inserting braces like {,} in a C function and declaring variables inside was a way to get away from the restrict that variables declare only at its beginning. C uses static scope, and braces are used to define scope. This will still true, because true, dynamic scoping is too complicated to implement for high efficient language like C.

But there are other techniques which work but not good.
Using negative index for manipulating 2D array is wise, but using zero sized array without knowing that there are C/C++ compilers which don’t support it is not good.

I would like to present one bad style of using virtual functions which works.
What is virtual function for? When you want to manipulate several objects of children class of parent class “CParent”, you can point those children objects with a pointer variable of CParent. If early binding is used, children objects are casted to the CParent. So, whatever methods you call, the methods of CParent are called, instead of the childrens’.
So, to enable late binding, virtual keyword is used.

So, when a method is called using the CParents’ pointer, it is better to step into its children’s method with late binding technique.

Now take a look at this.

class IWriteHandler
{
public:
    virtual void Run(int first, bool _fileMode, bool unicode)
    {
    };

    virtual void Run(int first, bool _fileMode, bool unicode, int paramsLength, void * pParams)
    {
        Run(first, _fileMode, unicode );
    }
};

class CDIFWriteHandler : public IWriteHandler
{
    int idNum;
public:
    virtual void Run(int first, bool _fileMode,bool unicode);
    
};

IWriteHadler *writeHanlder = new CDIFWriteHandler;
writeHandler->Run( first, fileMode, unicode, paramLength, &pParams );

Let’s think about what will be called when writeHandler->Run()… is reached.
The Run() with 5 parameters is called, and it calls Run() with 3 parameters.
Then what Run() will be called? That of the parent, or that of CDIFWriteHandler?
What is called is the one from CDIFWriteHandler.
If you step the code with the Visual C++ debugger, it reaches the Run() call inside of the Run() with 5 parameters, and goes until its ending brace. Then it steps into the CDIFWriteHandler’s Run() method.
Here, let’s think about modularity. C++ is for object oriented programming. One aspect of OOP is data encapsulation and data hiding. What it actually means is that you don’t need to worry about implementation of other class.
Cosidering that, the coding style above is not good, because you should care about implementation of children class. And the way the Run() of child class is not good.
Instead of stepping into the Run() of the child class directly, it passes the Run() line, and when it reaches the ending brace, it steps into the Run() of the child class.

Then how about this?

class CDIFWriteHandler : public IWriteHandler
{
    int idNum;
public:
    virtual void Run(int first, bool _fileMode,bool unicode);
    virtual void Run(int first, bool _fileMode, bool unicode, int paramsLength, void * pParams);
};

If you declare and define the Run() with 5 parameters, when writeHandler->Run( ) is called, the Run() with 5 parameters of CDIFWriteHandler is called directly.
Also, if you define the Run() just like the one in the IWriteHandler, Run() with 3 parameters in the CDifWriteHandler is its own Run() with 3 parameters. It means that you don’t need to pay attention to its parent class.
So, it refers its own method.

If the meaning of the virtual function is considered, this is the right way of defining and declaring virtual functions.

There is one thing bad about the 1st style shown above. When you deal with huge code base with lots of classes, and it is not written by you, you have no idea what classes are involved without checking the codes thoroughly. But if you stick to the 2nd style, you only need to pay attention to the current class implementation.

Although the 1st style works, but it is not good to use it.

Leave a comment