/** \file * This is an attempt to answer the Stack Overflow question "Override method * which has the same name as the class," wherein I ask how one would go about * implementing a virtual method of some derived type which happens to have the * same name as the method I need to implement. * * http://stackoverflow.com/questions/38384075/ * * Two methods are proposed, one using a typedef and the other using static * polymorphism (see below for implementation). The conclusion is there are * clear advantages to using the typedef solution, as the static polymorphism * solution does not solve the issue for all potential callers (specifically: * calls of the method inside of template functions). **/ /** \def USE_TYPEDEF * Flip between 0 and 1 to toggle the different ways to hack around a class * with a method named the same as the type. * * - 0: typedef foo_intermediate to be named foo * - 1: static polymorphism: create a class named foo and derive from * foo_intermediate **/ #define USE_TYPEDEF 0 #include /** The base class with an annoyingly-named function \c foo. **/ class base { public: virtual ~base() { } virtual void foo() const = 0; }; /** In both solutions, you create an intermediate class which actually * implements the foo method. **/ class foo_intermediate : public base { public: #if USE_TYPEDEF /** In the typedef variety, you would actually implement the whole class in * the thing I'm calling "intermediate" here. **/ virtual void foo() const override { std::cout << "Typedef works!" << std::endl; } #else /** In the static polymorphism solution, this forwards to the derived foo * that I actually want to use. The definition must appear after the * declaration of foo. **/ virtual void foo() const override; #endif }; #if USE_TYPEDEF // The typedef is pretty simple... using foo = foo_intermediate; #else /** In the static polymorphism solution, you derive from the intermediate class * and forward the constructor along. **/ class foo : public foo_intermediate { public: using foo_intermediate::foo_intermediate; private: friend class foo_intermediate; /** Actual implementation for the foo function goes here. **/ void foo_impl() const { std::cout << "Intermediate class works" << std::endl; } }; /** This would probably live in some CPP file. **/ void foo_intermediate::foo() const { static_cast(this)->foo_impl(); } #endif #if USE_TYPEDEF /** With the typedef, you can use a template parameter, since T is really a * foo_intermediate, so calling foo is legal. **/ template void call_foo(const T& x) #else /** You must refer to calling foo with something that is not a type named foo * (in this case, a reference to base). **/ void call_foo(const base& x) #endif { x.foo(); } int main() { foo x; #if USE_TYPEDEF // Can only be called directly with the typedef x.foo(); #else // With the intermediate class, you have to use an alias base& rx = x; rx.foo(); #endif // Demonstrates the same concept as above, but shows that the type name will // leak out to templates call_foo(x); }