Consider the below simple program of inheritance
#include <iostream>
class A
{
};
class B : public A
{
};
class C : public B
{
};
int main()
{
C x;
}
Now my question is
How many objects are created ? One or three?
Also, in case one object, does it mean it creates a layered object ?
What I wanted to ask was ,when we call constructor of base classes , what is happening as we have only one object (from the object perspective) ? What all things C object x will have ,and what all things are deleted when destructors of base class is called?
How is memory allocated for C's object?
Just to make everyone know ,I do understand
When we are creating an object of the derived class, we end up with one object only .
But the question is ,internally do the derived class object c will wrap the two objects of A and B or , will just public/protected attributes will be copied to the object.
Also is the below line correct?
"When we declare a object on the stack or use new first the memory is reserved and object is created, then the constructors are executed, starting with the base constructor and working upwards towards the most derived class ?"
Only one object of type class C would be created.
So basically in this case, constructors of base classes are called first before the constructor of the derived class is called. In the end, the object of derived class also contains the contents of bases classes.
One object is created, of type C, which contains all of the members of A, B, and C.
Here are some additional information about the relation between a base-class object and a derived-class object:
Every derived object contains a base-class part to which a pointer or reference of the base-class type can be bound. That's the reason why a conversion from derived to base exists, and no implicit Conversion from base to derived.
A base-class object can exist either as an independent object or as part of a derived object.
When we initialize or assign an object of a base type from an object of a derived type, only the base-class part of the derived object is copied, moved, or assigned. The derived part of the object is ignored.
see "C++ Primer Fifth Edition" §15.2.3
Related
In object slicing,when a derived class object is copied to a Base class object , does the _vptr of Derived class also gets copied to _vptr of Base class like other members of class Base?.If not why?
class Base{
public :
virtual void Display(){cout<<"In Base"<<endl;}
};
class Derived:public Base{
public:
void Display(){cout<<"In Derived"<<endl;}
};
int main()
{
Derived objD;
Base objB;
objB = objD;
objB.Display();
}
I have observed the following result for the above snippet.
Output
In Base
The vptr is NOT copied. Let's try to reason about why.
Looking at your main function:
Derived objD;
Base objB;
objB = objD; // <-- HERE
objB.Display();
In line 3, you are assigning objD to objB. This is actually calling Base's assignment operator (which is automatically defined):
Base& operator=(const Base& other)
and it is being passed objD as a Base&. So, your question becomes, "Does the assignment operator copy the vptr"? The answer is, "no". The default assignment operator only copies fields on the class.
You may then ask, "Why wouldn't it copy the vptr too?" The reason is that, if it copied the vptr, methods on the Base class would end up using methods implemented on the Derived class. However, in full generality, those methods could use data members that only exists on the Derived class (and that don't exist on the Base class). Calling those methods would therefore be nonsensical (the data logically doesn't exist on the Base class), and so the language rightly chooses not to do this.
The main issue is that, when you assign the Derived class to the Base class, the variable you're assigning to only holds the fields for the Base class, so the fields in the Derived class that aren't in the Base class are not copied. Therefore, methods from the Derived class won't make sense when called on the Base class.
Note that this isn't the case if, instead, you were to assign a Base pointer or a Base reference to the Derived class. In that case, the original Derived class instance still exists. It's sitting in memory somewhere and has all the Base+Derived class fields. Therefore, methods for the Derived class called on that instance will have access to those fields, and so being able to call those methods still makes sense.
This is why, in C++, to do polymorphism (via virtual methods), you need to use a reference or pointer. See here for a similar discussion:
Why doesn't polymorphism work without pointers/references?
All known implementations use vptr but the details vary a lot. The vptr is a way for implementations to represent the type of an object of a polymorphic class (class with virtual functions) and sometimes classes with virtual base classes (very implementation dependent).
Note that in many cases involving more than simple inheritance (single non virtual inheritance) classes have more than one vptr.
The vptr value is a function of the type of the most derived object constructed.
The type of an object cannot be changed by the user during its lifetime; during construction, the type of the object changes as it is being constructed; during destruction, it changes back. (It is illegal to refer to an object during construction or destruction with a name or other expression that has a type that doesn't match the object.)
You can reuse the space of an existing object to construct an object of a different type, but it isn't the same object:
struct X {
A a;
B b;
// requires: construction doesn't throw
};
void replace (X &x) {
x.~X();
B &b = *new (&x) B; // hope no exception here
b.f(); // use as a normal B object
x.f(); // undefined: cannot use x as a real object
X *p = &x; // legal: x isn't used as an object, only as an address
b.~B(); // clean up ressources if needed
new (&x) X; // valid: &x refers to storage, as if a void*
// x refers to a valid X object
}
Such object reuse doesn't change the type of any existing object: replace(x) doesn't just act on x (it does by destructing one and reconstructing one), it acts on the storage location of x. After calling replace(x) the name x can be used to refer to the newly constructed X object, which has effectively taken the identify of the previously existing X object.
No operation on an object (that keeps the object alive) is even allowed to change its type in C++. There is no way for a vptr to change on a constructed object.
Changing the type of a declared object would wreck the C++ types system and the invariants of declared objects. The compiler wouldn't know what class to destroy, which virtual functions to call, where the base classes are, etc. It would completely change the way C++ works. It's hard to even imagine the semantics associated with changing the type of an existing object.
I know that when assign the derived object to base object, the slicing happens. The first part of derived class object will copied to the base object.
And here is my quesition:
Will the vptr(virtual table pointer) be copied to base class object?
If vptr is not copied to base class object(I guess, for the object assignment will not cause polymorphism), why? Is there any rule to support that?
No, no vtable pointer is copied. Nor could it be, since the destination object is truly of base class type both before and after the assignment.
Virtual methods called on a sliced object will invoke the base class implementations.
I have written a pure virtual destructor and implemented it in the abstract base class and override it in derived classes.
However, in one of the classes I have a pointer to a base class object.
Now, should the destructor of the derived class be written this way:
virtual ~DerivedClass()
{
delete this->pointerToAnotherDerivedClassObject;
}
or will the object be deleted automatically? As the base class destructor is always called so I cannot decide whether it takes care of it or not.
EDIT: My mistake for stating it was a pointer to a base class, as it is actually a pointer for another derived class object.
However, in one of the classes I have a pointer to a base class object.
Now, should the destructor of the derived class be written this way
Since pointerToAnotherDerivedClassObject points at another object in memory, then yes, your DerivedClass destructor needs to explicitly delete that object (or wrap the raw pointer inside a smart pointer - std::auto_ptr, std::unique_ptr, or std::shared_ptr - and let it delete the object for you) ONLY IF DerivedClass is meant to own that other object. Otherwise, do not delete it if you do not own it.
#Elia Similar situation is discussed in the book of Eckel " thinking in C++ vol-2 " in design pattern chapter-10 regarding pseudo virtual constructor. The answer to your question is you do need to delete it considering you allocate it dynamically. Also don't confuse member Base* with the Base object which is part of derived due to inheritance, one is a data member (which is what you want to delete) other is due to inheritance.
If I have the following classes :
class Object { ... }
class MyClass1: public Object { ... }
class MyClass2: public Object { ... }
and a stack : std::stack<Object> statesObjects;
MyClass1 c1;
MyClass2 c2;
statesObjects.push(c1); // okay
statesObjects.push(c2); // okay
How can I pop them out and retrieve the element at the head of the stack (with top() ) without dynamic_cast , since I don't work with pointers here ?
The short answer is, that with your stack as-is you can't pop out the elements as derived-class type elements. By putting them into the stack you have sliced them to the element class of the stack. That is, only that base class part has been copied into the stack.
You can have a stack of pointers, however, and then you can use dynamic_cast provided that the statically known class has at least one virtual member function, or as the standard says, provided that the statically known class is polymorphic.
On the third and gripping hand, however, instead of the Java-like downcast use a virtual function in the common base class. Often it works to just directly have such a function. For more complicated scenarios you may have to use the visitor pattern (google it), but basically, the idea is that virtual functions are the “safe” language-supported type safe way to achieve the effect of downcasts.
You cannot pop them out to their original classes, when you assign a subclass to an instance of the superclass, it gets sliced into an instance of the superclass. i.e copies of c1 and c2 which are in the stack are now instances of Object and not their original classes
Similar to How can I make the method of child be called: virtual keyword not working?
Even if you seeminlgy store a derived class object in your class, what gets stored is only the Base class part of the object. In short You get Object Slicing.
To summarize, you cannot store derived class objects in this container. You will need to store a pointer to Base as the type of conainter and use dynamic polymorphism to acheive this.
Good Read:
What is object slicing?
I am new in C++ and I have just started studying polymorphism. I know that if I create an object for the derived class then the constructor of both derived and base class is get called. Does it mean that, when I create an object for the derived class, eventually I am ending up with two objects- one is created by the constructor of base class and another one created by the constructor of derived class?
Can anyone explain, what is the job of base class constructor when I want to create an object for the derived class.
The job of the base class constructor is to initialise the base class member variables (consider the case of a private member variable in the base class).
When you call a constructor for a derived object, you only end up with one object. The base class constructor initialises the base class parts of the new object, and the derived constructor initialises the derived class parts of the same new object.
Constructors do not allocate space and initiate instances of objects; they initialise the object immediately after space has been allocated.
When you declare a object on the stack or use new first the memory is reserved and object is created, then the constructors are executed, starting with the base constructor and working upwards towards the most derived class.
You will end up with a derived class object, that contains a base class object.
Constructors don't magically create another instance of an object. They initialise a certain piece of memory, but calling a constructor and allocating memory are not the same thing -- the latter is either done behind the scenes (for objects with automatic and static storage duration) or with new and malloc (for objects with dynamic storage duration).
EDIT: Before I get angry comments about it: "behind the scenes" is a vague way to put it; the definition of an object with automatic or static storage duration ensures that it gets memory.
Whether you are creating an object of the base class or derived class, you end up with one object.
Just because the base class constructor is called, it doesn't mean you get one extra object for that call. Here, the base class constructor will be executed, which typically sets attributes of the base class. The object on the whole would be composed of the base class properties and derived class properties.
If you have a class then you would have to define a contructor or constructors (there are certain circumstances in where you do not have to). A constructor has the purpose to initialise the class data members, you give a value to its data members. Any data member that you do not give it a value, will have an undefined value unless the data member is an instance of a class that happens to have a default constructor.
So when you create an instance of that class, the compiler will invoke the appropriate constructor, and the members of the instance that you have just created will have data initialised with values as you set them in the constructor.
If you have a derived class, you can add data members to it, but remember that it has also an inherited member: the base class. So when you define a constructor in you derived class, you must invoke a constructor of the base class (so that the members of the base class get fully initialised) and assign value to the derived class own data members.
So you create an instance of the derived class, the derived class constructor is invoved. As part of its functionality it invokes the constructor of its base class (so you might say two constructors but this is the wrong of viewing it).
If you create an instance of the base class, only that constructor is invoked.
When we create an object, Constructor will be called. Its not when constructor called object is being created.
You can assume Creating object as a function and Constructor is another function which is called inside it.
Assume A is a base class and B is a derived class,
class A
{
}
class B : public A
{
}
We will be creating object for class A in below ways,
A obja;
or
A obja = new A();
In both cases you can assume a function Create is getting called,
A::Create()
{
A();
}
If you are creating Derived class B object then Create method of B will be called,
So internally Create method of B will look like below,
B::Create()
{
B();
A();
}
So when we create Derived class object first derived class initialization happens and then Base class initialization happen. It not means object is created twice.
Object will be created for the Call where you are creating object using.
B obj;
or
B obj = new B();
Calling the constructors are internal functionality as Constructors called in the Create function.
Note : Create function in the above code is done only for illustrative purpose.
when object of a derived class is created then constructor function of that class will be created first then to use the constructor function of the base class will be called by a separate object at the time of calling it will be invoked by that object.