I have been plunging my brains trying to figure this out all day today...Its 2 am now. Please, someone explain the following to me: I know the virtual clone method is there in each class to facilitate the use of virtual copy constructors since you cannot directly declare
*virtual Mammal (const Mammal & rhs);* in this manner. However, I cannot understand what the clone method is doing. Lets say for example, at the prompt, I enter 2. Then the switch statement creates a Cat object on the free store and assigns it to ptr. Then ptr is assigned to theArray[i]. This cycle continues until the for loop ends. Then it executes the next for loop with the addresses stored in theArray[i] accessing the speak method. you see "Meow" in the output. In the next step it access the clone method and the both the Cat copy constructor and the Dog copy constructor is called. How is this possible? And what are the steps taking place here? How does the Cat's clone method call the copy constructors? It is possible that I am not understanding the fundamentals of *this as I suspect that this is responsible for calling the copy constructor. -
#include <iostream>
-
-
using namespace std;
-
-
class Mammal
-
{
-
public:
-
Mammal():itsAge(1) { cout << "Mammal constructor...\n"; }
-
~Mammal() { cout << "Mammal destructor...\n"; }
-
Mammal (const Mammal & rhs);
-
virtual void Speak() const { cout << "Mammal speak!\n"; }
-
virtual Mammal * Clone() { return new Mammal(*this); }
-
int GetAge()const { return itsAge; }
-
protected:
-
int itsAge;
-
};
-
//copy constructor defined
-
Mammal::Mammal (const Mammal & rhs):itsAge(rhs.GetAge())
-
{
-
cout << "Mammal Copy Constructor...\n";
-
}
-
-
class Dog : public Mammal
-
{
-
public:
-
Dog() { cout << "Dog constructor...\n"; }
-
~Dog() { cout << "Dog destructor...\n"; }
-
Dog (const Dog & rhs);
-
void Speak()const { cout << "Woof!\n"; }
-
virtual Mammal * Clone() { return new Dog(*this); }
-
};
-
-
Dog::Dog(const Dog & rhs):
-
Mammal(rhs)
-
{
-
cout << "Dog copy constructor...\n";
-
}
-
-
class Cat : public Mammal
-
{
-
public:
-
Cat() { cout << "Cat constructor...\n"; }
-
~Cat() { cout << "Cat destructor...\n"; }
-
Cat (const Cat & rhs);
-
void Speak()const { cout << "Meow!\n"; }
-
virtual Mammal * Clone() { return new Cat(*this); }
-
};
-
-
Cat::Cat(const Cat & rhs):
-
Mammal(rhs)
-
{
-
cout << "Cat copy constructor...\n";
-
}
-
-
enum ANIMALS { MAMMAL, DOG, CAT};
-
const int NumAnimalTypes = 3;
-
-
int main()
-
{
-
Mammal * theArray[NumAnimalTypes];
-
Mammal * ptr;
-
int choice, i;
-
for ( i = 0; i<NumAnimalTypes; i++)
-
{
-
cout << "(0)Mammal (1)dog (2)cat: ";
-
cin >> choice;
-
-
switch (choice)
-
{
-
case DOG: ptr = new Dog;
-
break;
-
case CAT: ptr = new Cat;
-
break;
-
default: ptr = new Mammal;
-
break;
-
}
-
theArray[i] = ptr;
-
}
-
Mammal * OtherArray[NumAnimalTypes];
-
-
-
for (i=0;i<NumAnimalTypes;i++)
-
{
-
theArray[i]->Speak();
-
OtherArray[i] + theArray[i]->Clone();
-
-
}
-
-
for (i=0;i<NumAnimalTypes;i++)
-
OtherArray[i]->Speak();
-
-
system("pause");
-
return 0;
-
}
-
10 2252
constructor - Dog::Dog(const Dog & rhs)
code - return new Dog(*this);
'this' variable here is a pointer to the class instance, of the type Dog*, then it is dereferenced to the type Dog& and passed to constructor. It works the same way as if they were - constructor - Dog::Dog(const Dog* rhs)
-
code - return new Dog(this);
-
A clone is a copy.
In C++ you create a clone by using the copy constructor.
In languages other than C++ where there is notjhing like a copy constrcutor, you need to write a clone method to make the copy.
Thanks for the responses. But I am sorry, i'm still not getting the complete picture. Let me know if this is correct: in the virtual function:
virtual Mammal * Clone(){return new Dog(*this)}
It creates a Dog object on the free store and assigns the calling object's contents to this newly created Dog. Then it returns a pointer to a Mammal. Then this pointer is stored in OtherArray[i] which will iterate to display all the speak methods. A mammal pointer is able to access the correct speak methods in Dog, Cat, etc because the speak method in Mammal is virtual. Am I correct so far? Now, the question is: When in this process is the copy constructor called? And what is the copy constructor doing? I really think I should understand this before moving on to polymorphism.
Yes you are correct.
This part
> assigns the calling object's contents to this newly created Dog.
actually happens within copy constructor, when parent constructor is called -
and copies the only member (age) from rhs into constructing object.
When is it called? During 'new' operator, after memory is allocated.
Thanks for the explanation newb16. I now understand that the new Dog gets its age copied to it inside the copy constructor. So when the Dog clone() method is called, I see 2 events take place:
1. A new Dog object is created on the free store.
In between these two steps, the Mammal copy constructor is called first with the address in *this and then the Dog copy constructors is called with *this. And inside the copy constructor, the value of age is copied into the new object. So basically *this is calling these copy constructors?
2. A Mammal pointer to this object is returned to the invoking object which is theArray[i] and the address is assigned to OtherArray[i].
I think I finally understand this correctly thanks to newb16 and others. Please see my comments in the code below and let me know if I my understanding is right or wrong. Thanks for your patience with my rather long comments.
This code in the Mammal class: - virtual Mammal * Clone() { cout << "mammal clone called" << endl; return new Mammal(*this); }
should be: - virtual Mammal * Clone() { return 0; }
This make the method a hook. A hook can be overridden in a derived class but the derived class is not forced to to do this.
Suppose have the address some Mammal object in ptr: - Mammal* obj = ptr->Clone();
If the object pointed at by ptr is a Mammal class that did not override Mammal::Clone(), then you haven't got a clone. You have a Mammal created from the Mammal portion of the ptr object. The rest of the ptr object has been sliced off. (Research on slicing).
By having Mammal::Clone() return a 0, then if a derived class does not implement Clone() then you cannot clone objects of thise classes. The caller just verifies that the Mammal* returned after the call to Clone() is not null.
Thanks for the explanation. But I am trying to understand the code in this book that I am learning with i would like to know if I am understanding this specific code correctly.
Many books have poor examples. In the case of hierarchies using virtual functions the going-in position is that:
1) you will create a derived object.
2) you will refer to the derived object using only a base class pointer
3) when you call a base class method, the call is diverted to the derived class method (if available).
Therefore, your Mammal* may not point to a Mammal. Therefore, the Clone() of Mammal returns a bad object if a) the actual object is not a Mammal and b)the actual object does not support Clone().
I understand about trying to work through your textbook but I want you to understand that in all design there is a downside. Not seeing the downside in C++ will cause you more trouble than you can imagine. Maybe what I say does not apply in this case but I guarantee that it will apply in a case you encounter later on. Maybe at that time you remember this series of posts and go "Wait a minute...".
You're absolutely right about books. I tried to contact the author of the book and his email is no longer valid. I am going to make the changes you've posted and report back. Thanks.
Sign in to post your reply or Sign up for a free account.
Similar topics
by: ccs |
last post by:
In Meyers' book he gave an example of "virtual copy constructor", which is
quite different to an "ordinary" copy constructor by:
1. it returns a pointer to an object instead of a reference.
2. it...
|
by: RonHiler |
last post by:
My copy constructor is crashing my program, and I can't figure out
why. I'll try to make the code listing as short as I can. Here are
the two headers:
class BreakthroughClass
{
public:...
|
by: jonathan cano |
last post by:
QUESTION:
In practice, lines 36 and 37 below are usually equivalent to the
default copy constructor (.e.g line 33). My questions are:
(a) Does ISO 14882 guarantee that lines 36 and 37 are...
|
by: Jeff Mallett |
last post by:
VC++.NET gave me Compiler Error C2621, which states,
"A union member cannot have a copy constructor."
Yikes, that can't be true! As I understand it, *all*
class objects have copy constructors,...
|
by: Arne |
last post by:
In C++ we have a copy constructor. What is the equivalent in .Net? Would that
be a clone method?
|
by: lhr_cool_guy |
last post by:
The following code is compiling correctly on Visual Studio .NET 2003
but crashes. The problem is that the copy constructor is not being
called when it should be. Am I doing something wrong or is...
|
by: Marcin Kalicinski |
last post by:
Hi,
Having the following program:
#include <iostream>
struct A
{
A() { std::cout << "A::A()\n"; }
A(const A &) { std::cout << "A::A(const A &)\n"; }
|
by: Nindi73 |
last post by:
A few days a ago I posted my code for a deep copy pointer which
doesn't require the pointee object to have a virtual copy constructor.
I need help with checking that it was exception safe and...
|
by: Henrik Goldman |
last post by:
Hi,
Lets say you have class A which holds all data types as private members.
Class B then inherits from A and does *only* include a set of public
functions which uses A's existing functions for...
|
by: JD |
last post by:
Hi,
My associate has written a copy constructor for a class. Now I need to add
an operator = to the class. Is there a way to do it without change her code
(copy constructor) at all? Your help...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
| |