471,595 Members | 1,827 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,595 software developers and data experts.

"Virtual constructor" abstract base class - feasibility?

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
Jan 19 '06 #1
8 3871
On Thu, 19 Jan 2006 11:37:00 +0000, Asfand Yar Qazi
<ay****@qazi.f2s.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
No**********@Home.com
Jan 19 '06 #2
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.

Jan 19 '06 #3
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
Jan 22 '06 #4
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.

Jan 22 '06 #5
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::object 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

Jan 22 '06 #6
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
Jan 25 '06 #8
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

Jan 25 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

12 posts views Thread by cppaddict | last post: by
14 posts views Thread by mshetty | last post: by
5 posts views Thread by Duck Dodgers | last post: by
4 posts views Thread by Jon Shemitz | last post: by
4 posts views Thread by mwebel | last post: by
1 post views Thread by Bart Simpson | last post: by
reply views Thread by XIAOLAOHU | last post: by
reply views Thread by Anwar ali | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.