C++ Notes

Virtual destructors:

 

we need to declare the destructor in the base class as virtual, so that the compiler could access the destructor of the derived class:

class Base
{
public:
 Base(){ cout<<"Base c'tor\n";}
 virtual ~Base(){ cout<<"Base d'tor\n";}
};
/*********************************/
class Derive: public Base
{
public:
 Derive(){ cout<<"Derive c'tor\n";}
 ~Derive(){ cout<<"Derive d'tor\n";}
 };

int main()
{
 Base *basePtr = new Derive();
 delete basePtr;
 return 0;
}

Output:
outputVirtual

 

 

However, when we remove the Virtual key-word from before ~Base(), we get the output:
q

 

Protected Constructors:

when declaring the constructors as protected in the base class, we convert the class to be sort of abstract, since we cannot create an object out of this class because the constructor is unassailable. However, it is accessible from within the other classes that inherit from it, therefore, the behavior of such  class is equivalent more or less to that of an abstract class.

Private Copy C’tor and operator=

In relation to the previous paragraph, we can also declare the copy c’tor as a private method, and that also a ‘encapsulation’ and ‘security’ feature for preventing the cloning of the class objects whenever we’re not interested in cloning them. see here.

However, it’s worth noting that if the Base class has it’s copy c’tor private, then we’ll have a compilation error if we tried to use the copy c’tor on a derived object.
Let’s take this code as example:

class Base
{
public:
 Base(){ cout<<"Base c'tor\n";}
 ~Base(){ cout<<"Base d'tor\n";}
 Base(const Base& baseObj) {cout<<"Base copy c'tor\n";}
private:
 /*no private fields*/
};
/*********************************/
class Derive: public Base
{
public:
 Derive(){ cout<<"Derive c'tor\n";}
 ~Derive(){ cout<<"Derive d'tor\n";}
 };
int main()
{
 cout<<"creating d1:\n";
 Derive d1 = Derive();

 cout<<"\ncreating d2:\n";
 Derive d2 = Derive(d1);
 cout<<"--------------------------\n";
 return 0;
}

In the example above, we defined a copy c’tor in the base class, but not in the derived. However, we declared ‘d2’ using a copy c’tor of Derived!
The output from the above code is:

note how the Base copy constructor is called when we tried to use the copy c'tor on an object of type Derive
note how the Base copy constructor is called when we tried to use the copy c’tor on an object of type Derive

Now, let’s make the copy c’tor of the Base as a private(so that Derive has no access to it  because private fields doesn’t pass with inhirtance), what will happen is a compilation error: “cannot access private member declared in class ‘Base'”

Temporary Objects

A temporary object is an object that has no name (and hence never has a real persistent memory allocated for it on the stack or heap etc.).  When you call a function with a parameter that is constructed on the fly:

CallMyFunction( Employee(..) )

the Employee(..) object is constructed on the fly and it never has a name.  Employee(..)resides in some temporary memory for the duration of executing CallMyFunction().

Now if this temporary object is not passed as a constant, CallMyFunction() can change it, a behavior that logically makes little sense (as no one outside CallMyFunction() can gain access to these changes) and hence forbidden in C++.

if still not sure about the temporary object behavior when assigned, then conducted the following experiment:

class A {
public:
 A(){}
 A(const A& a) { cout << "A copy ctor" << endl; }
 virtual ~A() { cout << "A dtor" << endl; }
 virtual void type() const { cout << "This is A" << endl; }
};
class B: public A {
public:
 virtual ~B() { cout << "B dtor" << endl; }
 virtual void type() const { cout << "This is B" << endl; }
};
/************************************************/
int main() {
 A a2 = B();
 a2.type();
 cout<<"----------------------\n";
 A& a = B();
 a.type();
 cout<<"------output end------\n";
 return 0;
}

The output:
q

You might wonder:
1) why the copy constructor of ‘A’ copies to ‘a’ an instance of ‘A’ rather than ‘B’?
2) why when ‘a’ was declared as ‘A&’ it was recognized as of type B?

Well, here we are mixing pointers/references to objects and objects.  a2 is an object and hence you cannot copy to it anything but type A object.  (The story was different if you defined a2 as a pointer to A, as “A *a2 = new B();” as you do for the reference in the second case).

Note B() constructs a temporary object of type B that is converted to type A for the copy constructor to be called and then immediately  B and the temporary converted A are destructed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: