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.