Same Name Class and Method

Let’s say I have a nice looking base class called base:

class base
{
public:
    virtual void foo() const = 0;
};

Now, I have a class named foo that I would like to inherit from base and override base::foo:

class foo : public base
{
public:
    virtual void foo() const override;
};

This is illegal in C++, as you are not allowed to name a method the same thing as the class. C++ believes methods with the same name as the class are constructors, which are not allowed to have return types. Is there any way around this that does not involve changing the name of the class or method?

Intermediate Class

The ultimate problem here is nothing more than naming, so one workaround for this issue is to create an intermediate class to deal with the name issue. First things first, let’s define the intermediate class foo_intermediate:

class foo_intermediate : public base
{
public:
    virtual void foo() const override;
};

// class foo goes here

void foo_intermediate::foo() const
{
    static_cast<const ::foo*>(this)->foo_impl();
}

In a real implementation, foo_intermediate would not have any implementation – it exists solely to handle the poorly-named foo function. Another gotcha is the definition of class foo must go where the comment says, as the contents of foo_intermediate::foo make use of the foreign class.

Let’s define the class foo that users will actually use:

class foo : public foo_intermediate
{
private:
    friend class foo_intermediate;

    void foo_impl() const
    {
        std::cout << "Real stuff goes here." << std::endl;
    }
};

There are some major disadvantages to this method. While calling b.foo() works perfectly fine (b is a const base&), there are two situations that do not work. The first is that you cannot directly call foo() on a const foo&:

foo x;
x.foo();

For the same reasons, you cannot call foo() when your const foo& is a template parameter:

template <typename T>
void call_foo(const T& x)
{
    x.foo();
}

void bar()
{
    foo x;
    call_foo(x);
}

Both of these cases work fine if you cast x to a const base& first, but that is super annoying.

Type Definition

Another solution is to use a type definition to deal with the naming. Start with a similar foo_intermediate:

class foo_intermediate : public base
{
public:
    virtual void foo() const override
    {
        std::cout << "Hello again" << std::endl;
    }
};

Then, give people a friendly name:

using foo = foo_intermediate;

This solution has neither of the disadvantages the intermediate class had. In fact, the only downside I see is that backtraces and breakpoints will be slightly less obvious.

More Info

This was inspired by the Stack Overflow question: C++: Override method which has the same name as the class of which the answers were a resounding no.

Source Code

Get the source code of this program same_name_ctor_and_method.cpp. It has been tested and compiled with g++ 6.2.1, but any compiler with C++ support should work just fine. Flip the value of USE_TYPEDEF to see the two options working.