Post on 20-Jan-2016
Reusing Code in C++
• Has-a relationship
• Classes with member objects(containment)
• The valarray template class
• Private & protected inheritance
• Multiple inheritance
• Virtual base class
• Template class
• Template specializations
Classes with object members
• A student class– A name (string class)– A set of quiz scores– A fixed-size array? dynamic memory
allocation?– An array-of-double
The valarray class
The Student class design
• Containment (composition, layering) is a has-a relationship
• Program studentc.h, studentc.cpp, use_stuc.cpp
Private inheritance
• With private inheritance, public and protected members of the base class become private members of the derived class
• Program studenti.h, studenti.cpp, use_studi.cpp
Containment or private inheritance
• Has-a relationship can be generated by containment or private inheritance
• In general, it is easy to use containment to build up a “has-a” relationship
• Private inheritance provides some privileges, such as accessing protected member, or redefining virtual function, which can not be implemented by containment
Containment or private inheritance
• We should use containment to model a has-a relationship
• Use private inheritance if the new class needs to access protected members in the original class or if it needs to redefine virtual functions
Varieties of inheritance
Redefining access with using
• Public members of a base class become protected or private when one uses protected or private derivation
Multiple inheritance
• Program worker0.h, worker0.cpp, worktest.cpp
Ambiguous inheritance
• Program worker.h, worker0.cpp, worktest.cpp // point out the ambiguities
Type conversion
class SingingWaiter:public Singer, public Waiter { };
SingingWaiter ed;
Worker *pw = &ed; // ambiguous
Worker *pw1 = (Waiter *) &ed; // the Worker in Waiter
Worker *pw2 = (Singer *) &ed; // the Worker in Singer
Inherit two base-class objects
Virtual base classes
class Singer : virtual public Worker { };
class Waiter : public virtual Worker { };
class SingingWaiter: pubic Singer, public Waiter { …};
Using virtual base class• If a class has an indirect inherit virtual base
class, a constructor for that class should explicitly invoke a constructor for the virtual base class unless all that is needed is the default constructor for the virtual base class– SingingWaiter(const Worker &wk, int p=0, int
v=Singer::other) : Waiter(wk, p), Singer(wk, v) { }
// flawed– SingingWaiter(const Worker &wk, int p=0, int
v=Singer::other) : Worker(wk), Waiter(wk, p), Singer(wk, v) { } // ok
Indicate which method
• Multiple inheritance can result in ambiguous callsSingingWaiter newhire(“Elise Hawks”, 2005, 6, soprano);
newhire.Show(); // ambiguous
newhire.Singer::Show(); // use Singer version
void SingingWaiter::Show() // best way to do it
{ Singer::Show();}
Problems shootingvoid Worker::Show() const{ cout << “Name:” << fullname << “\n”;
cout << “Employee ID:” << id << “\n”;}void Waiter::Show() const{ Worker::Show();
cout <<“Panache rating:” << panache << “\n”; }void HeadWaiter::Show() const{ Waiter::Show();
cout << “presence rating:” << presence << “\n”; }void SingingWaiter::Show(){ Singer::Show(); } // fail due to ignoring Waitervoid SingingWaiter::Show(){ Singer::Show(); Waiter::Show(); } // call Worker::show() twice
void Worker::Data() const{ cout << “Name:” << fullname << “\n”;
cout << “Empolyee ID:” << id << “\n”; }void Waiter::Data() const{ cout << “Panache rating:” << panache << “\n”;void Singer::Data() const{ cout << “Vocal range:” << pv[voice] << “\n”;}void SingingWaiter::Data() const{ Singer::Data(); Waiter::Data(); }void SingingWaiter::Show() const{ cout << “Category: singing waiter\n”;
Worker::Data(); Data();}• Program workermi.h, workermi.cpp, workmi.cpp
Using modular approach
Multiple inheritance synopsis
• A derived class with an indirect virtual base class should have its constructors invoke the indirect base-class constructors directly, which is illegal for indirect non-virtual base classes
• Name ambiguity is resolved via the dominance rule
Class templates• Inheritance and containment aren’t
always the solution when you want to reuse code
• Drawbacks of different datatype– Edit header file each time when one changes
the type– One can use the technique to generate just
one kind of the class per program
• C++ class template provide a better way to generate generic class declaration
• C++’s Standard Template Library (STL)
The original Stack class
Using a class template Stack
Stack<int> kernels; // create a stack of int
Stack<string> colonels; // a stack of string objects
Template<class T>
void simple(T t) { cout << t << “\n”; }
…
simple(2); // generate void simple(int)
simple(“two”);// generate void simple(char *)• Program stacktp.h, stacktem.cpp
Stack pointer – incorrect version
Stack<string> s; // original stackStack<char *> st; // create a stack for pointers-to-charstring po; • Three versions to replace “string po;”1. char *po; cin >> po; // error2. char po[40];
// template <class Type>// bool Stack<Type>::pop(Type &item)// { …; item = items[--top]; … }// item is Lvalue, cannot be array name
3. char *po = new char[40];// push to the same address, and pop the same address value// pop outcome is always the last push in data
Correct version
• Program stcktp1.h, stkoptr1.cpp
Array template• Template is usually used in container class
ArrayTP<ArrayTP<int, 5>, 10> twodee;
int twodee [10][5];• Program arraytp.h, twod.cpp• Generate 2 separate class declarations
• Just one class declaration through constructor
Template versatility
Using one than one type parameter
• Program pairs.cpp
Template specializations
• Template specializations– Implicit instantiation– Explicit instantiation– Explicit specialization
• Partial specialization
Implicit instantiation
• The compiler doesn’t generate an implicit instantiation of the class until it needs an object
Explicit instantiation
• Generate ArrayTP<string, 100> class
• The compiler generates the class definition, including method definitions, even though no object of the class has yet been created or mentioned
Explicit specialization• An explicit specialization is a definition for a
particular type of types that is to be used instead of the general template
• A specialized class template definition has the form
• To provide a SortedArray template specialized for the const char * type, using the current notation
Partial specializations• C++ allows for partial specializations,
which partially restrict the generality of a template
Partial specializations• Providing a special version for pointers• Making a variety of restrictions
• The compiler would make the following choices
Member templates
• Member templates– Program tempmemb.cpp
• Templates as parameters– Program tempparm.cpp
Template classes and friends
• Template class can have friends• 3 types of template friends
– Non-template friends– Bound template friends
• The type of the friend is determined by the type of the class when a class is instantiated
– Unbound template friends• All specializations of the friend are friends
to each specialization of the class
Non-template friend functions to template
classes
• counts() function is a friend to HasFriend<int> or HasFriend<string>
Bound template friends
• The compiler would replace the template parameter T with int, giving in this form
Bound template friends
• The report() function is not itself a template function, it just has a parameter that is a template
• Need to define explicit specializations for the friends one plans to use
Template class with non-template friends
• Program frnd2tmp.cpp
Bound template friend functions to template
classes• Bound template friend involves three
steps• Step 1, declare each template function
• Step 2, declare the templates again
Bound template friend functions to template
classes• Step 3, declare an object of a
particular specialization
• The compiler substitutes int for TT and generates the following class
Template friend to a template class
• Program tmp2tmp.cpp
Unbound template friend functions to template
classes
• show2(hfd, hfi2) gets matched to this specialization
• Program manyfrnd.cpp