Thursday 26 July 2012

Inheritance

Inheritance



Inheritance is used to write a specialized or enhanced version of another class. For example, an ofstream is a type of ostream. class D: public B defines class D as derived from (subclass of) base class (superclass) B, meaning that D inherits all of B's members, except the constructors, destructor, and assignment operator. The default behavior of these special member functions is to treat the base class as a data member. class String: public Vector<char> {
public:
String(const char* s=""): Vector<char>(strlen(s)) {
copy(s, s+strlen(s), begin()); // Inherits Vector<char>::begin()
}
};
String a="hello"; // Calls Vector<char>::Vector(5);
a.size(); // 5, inherits Vector<char>::size()
a[0]='j'; // "jello", inherits Vector<char>::operator[]
String b=a; // Default copy constructor uses Vector's copy constructor on base part
b=a; // Default = calls Vector's assignment operator on base part
The default destructor String::~String() {} is correct, since in the process of destroying a String, the base is also destroyed, calling Vector<char>::~Vector() {delete data[];}. Since there is no need to write a destructor, there is no need to redefine copying or assignment either.
Although String inherits Vector<char>::data, it is private and inaccessible. A protected member is accessible to derived classes but private elsewhere.
class B {
protected:
int x;
} b; // Declare class B and object b
b.x=1; // Error, x is protected

class D: public B {
void f() {x=1;} // OK
};
By default, a base class is private, making all inherited members private. Private base classes are rare and typically used as implementations rather than specializations (A string is a vector, but a stack is not). class Stack: Vector<int> { // or class Stack: private Vector<int>
public:
bool empty() const {return size()==0;} // OK
} s;
s.size(); // Error, private
s.empty(); // OK, public

A class may have more than one base class (called multiple inheritance). If both bases are in turn derived from a third base, then we derive from this root class using virtual to avoid inheriting its members twice further on. Any indirectly derived class treats the virtual root as a direct base class in the constructor initialization list.
class ios {...}; // good(), binary, ...
class fstreambase: public virtual ios {...}; // open(), close(), ...
class istream: public virtual ios {...}; // get(), operator>>(), ...
class ifstream: public fstreambase, public istream { // Only 1 copy of ios
ifstream(): fstreambase(), istream(), ios() {...} // Normally ios() would be omitted

No comments:

Post a Comment