Template overriding base class virtual function?

Discussion in 'C++' started by Peter Davis, Jul 24, 2012.

  1. Peter Davis

    Peter Davis Guest

    I'm trying to write something like a clone() method using the curiously
    recurring template pattern. What I'm doing is similar to what's
    described here:

    http://nerdland.net/2009/06/covariant-templatized-virtual-copy-constructors/

    but simpler, since I'm not worried about covariance. My clone() method
    will always return a Base*. So I have something like

    class Base
    {
    Base(){}
    Base(const Base& other){}
    virtual Base* clone(){Base b = new Base(); return b;}
    };

    // This template defines a clone() method with the same signature
    // as the one in Base.
    template <typename D> class Cloneable
    {
    public:
    virtual Base* clone() {Base b = new D(this); return b;}
    };

    // I think by inheriting from Cloneable, the clone() method in
    // Cloneable() should override the one in Base. But it doesn't.
    class Derived : public Base, public Cloneable<Derived>
    {
    Derived() : Base() {}
    Derived(const Derived& other) : Base(other) {}
    }

    When built with Visual Studio 2008, at least, the debugger shows me that
    it's the Base::clone() function that always gets called, instead of the
    one derived from Cloneable.

    If I make both Base and Cloneable be virtual base classes, this works,
    but I don't understand why this is necessary. Why doesn't the template
    just override the Base definition of clone()?

    Thanks!
    -pd

    --
    ----
    The Tech Curmudgeon
    http://www.techcurmudgeon.com
    Peter Davis, Jul 24, 2012
    #1
    1. Advertising

  2. Peter Davis

    Casey Guest

    On Tuesday, July 24, 2012 8:26:40 AM UTC-5, Peter Davis wrote:
    > If I make both Base and Cloneable be virtual base classes, this works,
    > but I don't understand why this is necessary. Why doesn't the template
    > just override the Base definition of clone()?


    Because "the template" (Cloneable<Derived>) doesn't derive from Base. Try:


    class Base
    {
    public:
    virtual Base* clone() const = 0;
    };

    template <typename D> class Cloneable : public Base
    {
    public:
    virtual Base* clone() const {
    return new D(*static_cast<const D*>(this));
    }
    };

    class Derived : public Cloneable<Derived>
    {};
    Casey, Jul 24, 2012
    #2
    1. Advertising

  3. Peter Davis

    Noah Roberts Guest

    On Tuesday, July 24, 2012 7:23:35 AM UTC-7, Casey wrote:
    > On Tuesday, July 24, 2012 8:26:40 AM UTC-5, Peter Davis wrote:
    > &gt; If I make both Base and Cloneable be virtual base classes, this works,
    > &gt; but I don&amp;#39;t understand why this is necessary. Why doesn&amp;#39;t the template
    > &gt; just override the Base definition of clone()?
    >
    > Because &quot;the template&quot; (Cloneable&lt;Derived&gt;) doesn't derive from Base. Try:


    Additionally, you'll want to review what happens when you have the same function defined in two unrelated base classes but don't hide it:

    http://crazycpp.wordpress.com/2011/03/28/name-resolution-and-overloading/
    Noah Roberts, Jul 24, 2012
    #3
  4. Peter Davis

    Peter Davis Guest

    On 7/24/2012 2:38 PM, Noah Roberts wrote:
    > On Tuesday, July 24, 2012 7:23:35 AM UTC-7, Casey wrote:
    >> On Tuesday, July 24, 2012 8:26:40 AM UTC-5, Peter Davis wrote:
    >> &gt; If I make both Base and Cloneable be virtual base classes, this works,
    >> &gt; but I don&amp;#39;t understand why this is necessary. Why doesn&amp;#39;t the template
    >> &gt; just override the Base definition of clone()?
    >>
    >> Because &quot;the template&quot; (Cloneable&lt;Derived&gt;) doesn't derive from Base. Try:


    Thank you. The actual code is more complex, as it is the implementation
    side of a pimpl pattern, but I'll see if I can adapt this.

    >
    > Additionally, you'll want to review what happens when you have the same function defined in two unrelated base classes but don't hide it:
    >
    > http://crazycpp.wordpress.com/2011/03/28/name-resolution-and-overloading/
    >


    Thanks. I think a big part of the problem is that I was not able to make
    the clone() method on Base be pure virtual. That's because there are
    other classes, also abstract, whose default constructors created new
    Base objects, so Base could not have any pure virtual methods.

    Thank you both!
    -pd

    --
    ----
    The Tech Curmudgeon
    http://www.techcurmudgeon.com
    Peter Davis, Jul 25, 2012
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page