Overloading, Is It really Worth It?

For a long time I’ve used overloading, but just recently I’ve been questioning its uses.

Readability

Looking at the call site when invoking an overloaded function its not immediately obvious which method is being called.

find("code buddy");
find(C_PLUS_PLUS);

After a quick look through the overloading options available I can always work out which one will be called – but why should I? If code is making me think more than is absolutely neccessary then for my money, there is an issue with it. Wouldn’t the previous code be clearer if it was written like this:

findByName("code buddy");
findByLanguage(C_PLUS_PLUS);

Tags

My poor tags get confused! I’m working in a C++ code base on a linux OS. Rightly or wrongly, I’m using emacs with cscope as my chosen editing/tagging solution.  For example, if I’m working with the Visitor Pattern that is using overloading for its visit method, as search for:

void visit(const NodeA& node);

also finds me:

void visit(const NodeB& node);
void visit(const NodeC& node);

This maybe a shortcoming of cscope, however I’ve seen other tagging solutions, notably the one used in Slick Edit fall at the same hurdle.  I’d much rather see this visitor interface written like this:

virtual void visitNodeA(const NodeA& node) = 0;
virtual void visitNodeB(const NodeB& node) = 0;
virtual void visitNodeC(const NodeC& node) = 0;

Templates

It maybe nessary for templatised code that you use overloading, eg:

template<Node>
void doSomeStuffAndVisit(IVisitor& visitor,
                        const Node& node)
{
    // some code
    visitor.visit(node);
    // some more code
}

Constructors

Overloading of constuctors is unavoidable.

// Creates a Foo from the xml in file file
Foo::Foo(const std::string& file);
 
// Creates a Foo from the xml node root
Foo::Foo(const xmlNode& root);

Unless of course your using a factory method, in which case, there is no need to overload like this:

// Creates a Foo from the xml in file file
*Foo FooFactory::createFoo(const std::string& file);
 
// Creates a Foo from the xml node root
*Foo FooFactory::createFoo(const xmlNode& root);

The comments really are the give away here, taking the comments away things become so much more readable.

FooFactory::createFooFromFile(const std::string& file);
 
FooFactory::createFooFromXMLNode(const xmlNode& root);

Conclusion

These days, unless I’m working with any code thats using templates, i’m avoiding overloading, the pros are much outweighed by the cons.

Leave a Reply

Your email address will not be published.