"Virtual constructor" abstract base class - feasibility?

Discussion in 'C++' started by Asfand Yar Qazi, Jan 19, 2006.

  1. Hi,

    I have the following header file in my 'everything useful I think of
    in one place' library:

    ============= BEGIN CODE SNIPPET ===========

    /** All classes that derive from this obtain a 'virtual constructor' -
    ie if the 'clone()' method is called on a polymorphic type, an
    object of the same (unknown) type is returned. */
    class CloneService
    {
    public:
    virtual ~CloneService()
    {
    }

    /// This MUST be overridden in children classes. Abstract
    /// classes might want to override this too (and keep it
    /// abstract), as it will make it more convenient for users to
    /// use pointers of those classes.
    virtual CloneService*
    clone() const = 0;
    };

    /// Makes it easy to check at compile time if a given template
    /// parameter class has the 'clone' method.
    template<typename T>
    bool
    check_clone_service_requirements()
    {
    T* (T::*test)() const = &T::clone;
    test = test;

    return true;
    }

    ============= END CODE SNIPPET ===========

    Could someone tell me the feasibility of having something like this?
    I've used it in a few places and found it useful, but I always do
    something like:

    class Base : public CloneService
    {
    // ...
    Base* clone() const = 0;
    // ...
    };

    class Child : public CloneService
    {
    // ...
    Child* clone() const {return new Child(*this);}
    // ...
    };

    i.e. I have to redeclare the clone virtual method in the abstract
    virtual base class definition anyway. Can anyone thing of any
    situations where having a 'CloneService' base class for all cloneable
    classes everywhere would be useful?

    And I realise now that the name 'Cloneable' is a better one than
    'CloneService' - but that's what using too much Java does to you.

    Thanks,
    Asfand Yar

    --
    Entry in RollerCoaster Tycoon 2 readme.txt file:
    RollerCoaster Tycoon2 must be played on a video card capable of
    640x480 screen resolution at a bit depth setting of 256 bits.
    And the proof that playing too many strategy games causes loss of
    humour: http://tinyurl.com/dyrtt
     
    Asfand Yar Qazi, Jan 19, 2006
    #1
    1. Advertising

  2. On Thu, 19 Jan 2006 11:37:00 +0000, Asfand Yar Qazi
    <2s.com> wrote:

    >Hi,
    >
    >I have the following header file in my 'everything useful I think of
    >in one place' library:
    >
    >============= BEGIN CODE SNIPPET ===========
    >
    >/** All classes that derive from this obtain a 'virtual constructor' -
    > ie if the 'clone()' method is called on a polymorphic type, an
    > object of the same (unknown) type is returned. */
    >class CloneService
    >{
    >public:
    > virtual ~CloneService()
    > {
    > }
    >
    > /// This MUST be overridden in children classes. Abstract
    > /// classes might want to override this too (and keep it
    > /// abstract), as it will make it more convenient for users to
    > /// use pointers of those classes.
    > virtual CloneService*
    > clone() const = 0;
    >};
    >
    >/// Makes it easy to check at compile time if a given template
    >/// parameter class has the 'clone' method.
    >template<typename T>
    >bool
    >check_clone_service_requirements()
    >{
    > T* (T::*test)() const = &T::clone;
    > test = test;
    >
    > return true;
    >}
    >
    >============= END CODE SNIPPET ===========
    >
    >Could someone tell me the feasibility of having something like this?
    >I've used it in a few places and found it useful, but I always do
    >something like:
    >
    >class Base : public CloneService
    >{
    > // ...
    > Base* clone() const = 0;
    > // ...
    >};
    >
    >class Child : public CloneService
    >{
    > // ...
    > Child* clone() const {return new Child(*this);}
    > // ...
    >};
    >
    >i.e. I have to redeclare the clone virtual method in the abstract
    >virtual base class definition anyway. Can anyone thing of any
    >situations where having a 'CloneService' base class for all cloneable
    >classes everywhere would be useful?
    >
    >And I realise now that the name 'Cloneable' is a better one than
    >'CloneService' - but that's what using too much Java does to you.


    The problem I see is the fact that clients can now create containers
    of pointers to CloneService, although these might be otherwise totally
    incompatible types with no other methods in common. IOW, you have the
    same design problem as if every single type in your project might
    derive from a class called "CObject" (ever heard of MFC?)

    --
    Bob Hairgrove
     
    Bob Hairgrove, Jan 19, 2006
    #2
    1. Advertising

  3. Asfand Yar Qazi

    Axter Guest

    Asfand Yar Qazi wrote:
    > Hi,
    >
    > I have the following header file in my 'everything useful I think of
    > in one place' library:
    >
    > ============= BEGIN CODE SNIPPET ===========
    >
    > /** All classes that derive from this obtain a 'virtual constructor' -
    > ie if the 'clone()' method is called on a polymorphic type, an
    > object of the same (unknown) type is returned. */
    > class CloneService
    > {
    > public:
    > virtual ~CloneService()
    > {
    > }
    >
    > /// This MUST be overridden in children classes. Abstract
    > /// classes might want to override this too (and keep it
    > /// abstract), as it will make it more convenient for users to
    > /// use pointers of those classes.
    > virtual CloneService*
    > clone() const = 0;
    > };
    >
    > /// Makes it easy to check at compile time if a given template
    > /// parameter class has the 'clone' method.
    > template<typename T>
    > bool
    > check_clone_service_requirements()
    > {
    > T* (T::*test)() const = &T::clone;
    > test = test;
    >
    > return true;
    > }


    It only makes it easier, if you have the derive type to check it with.
    If your pointer does not match the derive type, then the above code
    will fail to catch the error at compile time.
    It's still better then nothing, but it's not fail proof.
    I use a similar method in the following policy class smart pointer:
    http://code.axter.com/smart_ptr.h

    If you look at the clone_static_function_allocator_policy, you'll see
    that it uses a static clone function, instead of the normal virtual
    clone function.

    If a derived type is used that doesn't have the static function
    declared, it will cause a compile time error.
    But this method also is not fail proof, since a derived pointer could
    be used to a derived-derived type, and than it will fail to produce an
    error if the derived-derived type has no clone function.
     
    Axter, Jan 19, 2006
    #3
  4. Bob Hairgrove wrote:
    <snip>
    >
    > The problem I see is the fact that clients can now create containers
    > of pointers to CloneService, although these might be otherwise totally
    > incompatible types with no other methods in common. IOW, you have the
    > same design problem as if every single type in your project might
    > derive from a class called "CObject" (ever heard of MFC?)


    Ah - I see. From now on, I will simply declare the virtual clone() function in
    every base class I produce, and they will be totally unrelated in terms of
    ancestry. Thanks for the advice

    --
    Entry in RollerCoaster Tycoon 2 readme.txt file:
    RollerCoaster Tycoon2 must be played on a video card capable of 640x480 screen
    resolution at a bit depth setting of 256 bits.
    And the proof that playing too many strategy games causes loss of humour:
    http://tinyurl.com/dyrtt
     
    Asfand Yar Qazi, Jan 22, 2006
    #4
  5. Asfand Yar Qazi

    Shark Guest

    Asfand Yar Qazi wrote:
    > Bob Hairgrove wrote:
    > <snip>
    > >
    > > The problem I see is the fact that clients can now create containers
    > > of pointers to CloneService, although these might be otherwise totally
    > > incompatible types with no other methods in common. IOW, you have the
    > > same design problem as if every single type in your project might
    > > derive from a class called "CObject" (ever heard of MFC?)

    >
    > Ah - I see. From now on, I will simply declare the virtual clone() function in
    > every base class I produce, and they will be totally unrelated in terms of
    > ancestry. Thanks for the advice


    I think clone() has more to do with prototype design pattern than with
    virtual constructor (factory design pattern). Ask in comp.object too.
     
    Shark, Jan 22, 2006
    #5
  6. Asfand Yar Qazi

    Luke Meyers Guest

    Asfand Yar Qazi wrote:
    > i.e. I have to redeclare the clone virtual method in the abstract
    > virtual base class definition anyway. Can anyone thing of any
    > situations where having a 'CloneService' base class for all cloneable
    > classes everywhere would be useful?


    I don't think it's useful, for the same reason that there isn't a
    common std::eek:bject base class, or even a common base class for all STL
    iterators. You're free to define clone() methods wherever you need
    them. Having a common parent which requires this (and doesn't solve
    the problem of multi-level inheritance) only allows you to treat all
    such objects polymorphically. Is there some OO justification for
    treating completely unrelated classes polymorphically? Not in any
    defensible design, I think.

    But yeah, tell that to Java.

    Look into compile-time polymorphism with templates. It accomplishes
    what you're trying to do, without necessitating meaningless
    inheritance. Once you grasp the point that inheritance is far from the
    only kind of relationship between types, you'll be a much happier
    coder.

    Oh, and read some books from the "C++ In-Depth" series, particularly
    Alexandrescu and Sutter.

    Luke
     
    Luke Meyers, Jan 22, 2006
    #6
  7. Asfand Yar Qazi

    Luke Meyers Guest

    Luke Meyers, Jan 23, 2006
    #7
  8. Luke Meyers wrote:
    >
    > Look into compile-time polymorphism with templates. It accomplishes
    > what you're trying to do, without necessitating meaningless
    > inheritance. Once you grasp the point that inheritance is far from the
    > only kind of relationship between types, you'll be a much happier
    > coder.


    Sometimes I need to clone something that I know the base type of, but do not
    know what the object actually is. That's what I need a virtual constructor (or
    whatever the design pattern people call it).

    >
    > Oh, and read some books from the "C++ In-Depth" series, particularly
    > Alexandrescu and Sutter.


    Will do.

    --
    Entry in RollerCoaster Tycoon 2 readme.txt file:
    RollerCoaster Tycoon2 must be played on a video card capable of 640x480 screen
    resolution at a bit depth setting of 256 bits.
    And the proof that playing too many strategy games causes loss of humour:
    http://tinyurl.com/dyrtt
     
    Asfand Yar Qazi, Jan 25, 2006
    #8
  9. Asfand Yar Qazi

    Luke Meyers Guest

    Asfand Yar Qazi wrote:
    > Luke Meyers wrote:
    > >
    > > Look into compile-time polymorphism with templates. It accomplishes
    > > what you're trying to do, without necessitating meaningless
    > > inheritance. Once you grasp the point that inheritance is far from the
    > > only kind of relationship between types, you'll be a much happier
    > > coder.

    >
    > Sometimes I need to clone something that I know the base type of, but do not
    > know what the object actually is. That's what I need a virtual constructor (or
    > whatever the design pattern people call it).


    Right, and that's fine. Because you know the base type, you can see
    the base type's virtual clone() member function and use it. That
    provides exactly what you'd want. Introducing a separate Cloneable
    parent just complicates the situation and gains you nothing.

    Luke
     
    Luke Meyers, Jan 25, 2006
    #9
    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.
Similar Threads
  1. Matthias Kaeppler
    Replies:
    1
    Views:
    471
    R.F. Pels
    May 22, 2005
  2. Sameer
    Replies:
    4
    Views:
    635
    Roedy Green
    Aug 31, 2005
  3. Uzytkownik
    Replies:
    3
    Views:
    610
    Uzytkownik
    Apr 3, 2005
  4. Iyer, Prasad C

    Abstract Methods & Abstract Class

    Iyer, Prasad C, Oct 20, 2005, in forum: Python
    Replies:
    0
    Views:
    552
    Iyer, Prasad C
    Oct 20, 2005
  5. Replies:
    4
    Views:
    866
    Rolf Magnus
    May 17, 2006
Loading...

Share This Page