Initialising classes with pointers to this

P

pauldepstein

I don't understand the following line of code. Please note that, as
my naming suggests, DerivedClass is a class that is derived from
BaseClass.

virtual BaseClass* clone() const{ return new DerivedClass(*this);

My confusion arises from the fact that DerivedClass appears only to
take the default constructor, initialised with ()

So how does DerivedClass(*this) make sense when all objects of
DerivedClass are constructed via a constructor with no parameters?

I know this is a basic question about a fairly common type of c++
construct, and I'm eager to learn more.

Thanks for your help,

Paul Epstein
 
C

Craig Scott

I don't understand the following line of code. Please note that, as
my naming suggests, DerivedClass is a class that is derived from
BaseClass.

virtual BaseClass* clone() const{ return new DerivedClass(*this);

My confusion arises from the fact that DerivedClass appears only to
take the default constructor, initialised with ()

So how does DerivedClass(*this) make sense when all objects of
DerivedClass are constructed via a constructor with no parameters?

If you don't declare a copy constructor, the compiler helpfully
provides one for you. You can prevent it from doing so by declaring a
private copy constructor without ever having to provide an
implementation (assuming you don't try to use it within the class
itself). In code, this might look something like the following:

class DerivedClass : public BaseClass
{
// This is private. We declare the copy constructor
// but never need to provide an implementation
DerivedClass(const DerivedClass&);

public:
// Declare the constructors you need here. Your comments
// suggest you only have a default constructor.
DerivedClass();

// ... other functions, etc. omitted
};
 
C

Craig Scott

Not really. A Clone method is most likely some programmer's obsession with
Java coming out in their C++ code. There is really no sense having a clone
method in C++. We overload operator = or provide a copy constructor.

A significant number of well respected people might disagree with you
on that point. ;) Having a function called clone() is a relatively
common design pattern that finds regular use in well design C++ code.
It is particularly powerful when used with covariant return types such
that subclasses can return their own more derived type even though the
base class declaration only specifies the base class as the return
type. See 10.3/5 of the current standard for details. I would not be
at all surprised if this feature of the C++ language was not created
with the clone pattern in mind.
 
M

Marcel Müller

Christopher said:
Not really. A Clone method is most likely some programmer's obsession with
Java coming out in their C++ code. There is really no sense having a clone
method in C++. We overload operator = or provide a copy constructor.

I do not agree to the last statement. In polymorphic classes there may
be a need to invoke the copy constructor in abstact base classes. And
since the C++ language does not provide a direct way to do this (most
other OO languages too), a virtual clone method is a common work-around.


Marcel
 
C

Craig Scott

Yea, I've seen that too. I think its a bunch of ick. Requiring the Abstract
class to know the definition of a derived classes, creating a circular
dependancy. I've also seen people implementing a derived class code
identifier in all the classes in order for the abstract class to tell "what
kind am I cloning". There are better solutions IMO.

Why must the abstract base class know the definition of a derived
class? Because the C++ standard allows for covariant return types, the
base class can be made completely oblivious to what subclasses are
defined (that's the whole point). For example:

class Base
{
public:
// Constructor and other functions omitted for clarity
virtual Base* clone() const = 0;
};

class Derived : public Base
{
public:
// Constructor and other functions omitted for clarity
virtual Derived* clone() const;
};


Note that the return type for the clone() function in Derived is
Derived*, not Base* as declared in the base class. I'm struggling to
see why the base class would need to know what type it is cloning.
Perhaps you could post an example?
 
C

Craig Scott

Why must the abstract base class know the definition of a derived
class? Because the C++ standard allows for covariant return types, the
base class can be made completely oblivious to what subclasses are
defined (that's the whole point). For example:

class Base
{
public:
// Constructor and other functions omitted for clarity
virtual Base* clone() const = 0;

};

class Derived : public Base
{
public:
// Constructor and other functions omitted for clarity
virtual Derived* clone() const;

};

Note that the return type for the clone() function in Derived is
Derived*, not Base* as declared in the base class.

Hmmm.... reading back over my post, I realized I neglected to explain
or show an example why the covariant return type is useful. I presumed
(perhaps incorrectly) by your comment that you needed somehow to get a
pointer to the derived class back from the clone() function rather
than a pointer to the base class. This was the need I was addressing
by the covariant return type feature. A bit of code using my Base/
Derived examples might make this clearer.

Derived d;
Base* bp = &d;

// Create a clone from the base class pointer.
// We get a Base* back, not a Derived*
Base* dClonedFromBase = bp->clone();

// Create a clone from the derived class.
// This time, we get a Derived* so we have
// the ability to call Derived member functions
// access its data members, etc.
Derived* dClonedFromDerived = d.clone();


In both cases, we get a full clone of the derived class, even though
cloning from the Base* pointer returns a Base* whereas cloning from a
Derived object gives us a Derived*. This feature allows you to use the
one function (clone() in this case) but still return the actual type
being cloned. In your client code, this means that whatever type you
are cloning from, you will have access to all member functions and
other member data of that type, not just the base class type. A bit
wordy, but I hope it's clear enough to get my point.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top