Click on inherit.cpp to get source.
// File: C++Example/inherit.C
// demo of constructors, destructors, inheritance, etc.
#include <iostream>
using namespace std;
class base {
public:
int size;
int *data_arr; // gets allocated by constructor
base (int n) : size(n)
{ cout << "base constructor with arg: " << n << endl;
data_arr = new int[n];
}
~base()
{ cout << "base destructor" << endl;
delete [] data_arr;
}
base() : size(10)
{ cout << "base constructor without arg" << endl;
data_arr = new int[10];
}
base(const base& b)
// this constructor makes a new object as a copy of b
{ cout << "base copy constructor" << endl;
size = b.size;
data_arr = new int[size];
for(int i=0; i<size; i++) data_arr[i] = b.data_arr[i];
}
base& operator=(const base& b)
// this operator "copies" into *this, which is an existing object
// if not explicitly defined, each member is assigned
// this causes 2 problems: a) this->data_arr and b.data_arr will point to
// the same array (which may not be desired)
// b) on destruction, the array is deleted twice
// (which may cause a run-time error)
// Note: if you really want to share objects, you must
// keep track of a reference count before deleting them
{ cout << "base assignment operator: COPIES ARRAY" << endl;
if (this != &b ) // guard against self assignment
{size = b.size;
delete [] data_arr;
data_arr = new int[size];
for(int i=0; i<size; i++) data_arr[i] = b.data_arr[i];
}
return *this;
}
friend ostream& operator<<(ostream&, const base&);
}; // end class base
ostream& operator<<(ostream& os, const base& b)
{os << "write base obj to stream: size = " << b.size;
return os;
}
class item {
public:
int x;
item (int m) : x(m)
{ cout << "item constructor with arg: " << m << endl;
}
~item()
{ cout << "item destructor" << endl;
}
item() : x(0)
{ cout << "item constructor without arg" << endl;
}
item(const item& it)
{ cout << "item copy constructor" << endl;
x = it.x;
}
item& operator=(const item& it)
{ cout << "item assignment operator" << endl;
if(this != &it)
x = it.x;
return *this;
}
friend ostream& operator<<(ostream&, item&);
};
ostream& operator<<(ostream& os, const item& it)
{os << "write item obj to stream: x = " << it.x;
return os;
}
class derive : public base {
public:
item it;
derive (int m, int n) : base(n), it(m)
{ cout << "derive constructor with args: "
<< m << ", " << n << endl;
}
~derive()
{ cout << "derive destructor" << endl;
}
derive()
{ cout << "derive constructor without arg" << endl;
}
derive(const derive& d) : base(static_cast<const base&>(d)), it(d.it)
// implements the default copy constructor
// only written to print on its invocation
{ cout << "derive copy constructor" << endl;
}
derive& operator=(const derive& d)
// implements default assignment operator
// only written to print on its invocation
{ cout << "derive assignment operator" << endl;
if( this != &d)
{static_cast<base&>(*this) = static_cast<const base&>(d);
// alternatively: base::operator=(static_cast<const base&>d);
it = d.it;
}
return *this;
}
friend ostream& operator<<(ostream&, const derive&);
};
ostream& operator<<(ostream& os, const derive& d)
{os << "write derive obj to stream: " << endl
<< " " << static_cast<const base&>(d) << endl
<< " " << d.it;
return os;
}
int main(int argc, char *argv[])
{ // 1. explicity create a derive object
// (this object must be explicity deleted)
cout << "1. new derive(5,20);" << endl;
derive* d1_ptr; d1_ptr = new derive(5,20);
cout << *d1_ptr << endl << endl;
// 2. create a derive object in an automatic variable
// (which will be deleted as soon as the var goes out of scope)
cout << "2. derive d2;" << endl;
derive d2; cout << d2 << endl << endl;
// 3. assign a derive object to another
cout << "3. d2 = *d1_ptr;" << endl;
d2 = *d1_ptr; cout << d2 << endl << endl;
// 4. create a derive object by copy through "initialization"
cout << "4. derive d3 = d2;" << endl;
derive d3 = d2; // Note: same as derive d3(d2); [NOT operator=]
cout << d3 << endl << endl;
// 5. assign to base object an expression whose type matches
// the type of a constructor parameter
cout << "5. base b; b = 4;" << endl;
base b1; b1 = 4; // Note: such an implicit conversion can be disallowed by
// declaring in class base: explicit base(int);
cout << b1 << endl << endl;
// 6. invoke the derive destructor
cout << "6. delete d1_ptr;" << endl;
delete d1_ptr; cout << endl;
// 7. various implict destructors will be invoked before returning
cout << "The end" << endl;
return 0;
}