I wrote a C++ code snippet to test which copy constructor will be called during object slicing. The code is as follows:
#include <iostream>
using namespace std;
class pet
{
public:
pet ()
{
cout << "pet default constructor" << '\n';
}
pet (pet & p)
{
cout << "pet copy constructor" << '\n';
}
~pet ()
{
cout << "pet destructor" << '\n';
}
void speak ()
{
cout << "Growl" << '\n';
}
};
class cat:public pet
{
public:
cat ()
{
cout << "cat default constructor" << '\n';
}
cat (cat & c)
{
cout << "cat copy constructor" << '\n';
}
~cat ()
{
cout << "cat destructor" << '\n';
}
void speak ()
{
cout << "Meow" << '\n';
}
};
int main ()
{
cat pussy;
cout << "create pussy before this line" << '\n';
((pet) pussy).speak ();
cout << "destroy pussy before leaving main()" << '\n';
return 0;
}
The output of this program is:
pet default constructor
cat default constructor
create pussy before this line
pet copy constructor
Growl
pet destructor
destroy pussy before leaving main()
cat destructor
pet destructor
I'm only interested in which copy constructor is called during object slicing, so let's focus only on the following part of the output:
pet copy constructor
Growl
pet destructor
I initially thought that when (pet) pussy
is executed, the program would first call the cat copy constructor to create a temporary object, then remove the cat part (derived class part) of the temporary object and keep only the pet part (base class part). Therefore, I expected the output to be:
cat copy constructor
Growl
pet destructor
However, the actual output is different. Can you explain why this is the case? Thank you in advance for your answer.
After reading the answer from @463035818_is_not_a_number, I realized that I had a misconception about the internal implementation of type casting. In fact, I'm not quite sure why pet& can be bound to a variable (pussy) of a different type, and what C++ does when implementing this feature.
I initially thought that when (pet) pussy is executed, the program would first call the cat copy constructor to create a temporary object, then remove the cat part (derived class part) of the temporary object and keep only the pet part (base class part).
No. Thats not what happens. When you cast, like in this line (replaced c-style cast with proper one):
(static_cast<pet>(pussy)).speak ();
The the constructor will look for a conversion from cat
to pet
. The constructor pet::pet(pet&)
can do that, because pussy
can bind to pet&
. No slicing is actually happening, no member data is lost. In other words, there are no members in pussy
that get lost by calling this constructor.
On this temporary pet
the member methods is called, then it is destroyed.