Week 10 Lecture Summary for CSC 309

These notes are not intended to be complete. They serve as an outline to the class and as a supplement to the text.


Polymorphism

Figure 7.1.2 from the Text

#include <iostream>
using namespace std;


class TradesPerson 
{
    public:
        virtual void sayHi() { cout << "Hi from on top." << endl; }
};
class Tinker : public TradesPerson 
{
    public:
        virtual void sayHi() { cout << "Hi, I tinker." << endl; }
};
class Tailor : public TradesPerson 
{
    public:
        virtual void sayHi() { cout << "Hi, I tailor." << endl;}
};
int main(int argc, char *argv[])
{
    TradesPerson *p;    // Pointer to base class
    int which;
    do {
        cout << "Enter 1 for TradesPerson, 2 for Tinker, 3 for Tailor" << endl;
        cin >> which;
    }while( which < 1 || which > 3);
    switch(which){
        case 1: p = new TradesPerson; break;
        case 2: p = new Tinker;  break;
        case 3: p = new Tailor;  break;        
    }
    p -> sayHi();     // run time binding
    delete p;
    system("PAUSE");
    return EXIT_SUCCESS;
}

 void virtual Tinker::sayHi() {
    { cout << "Hi, I tinker." << endl; }
 }
 virtual void  Tinker::sayHi() {
    { cout << "Hi, I tinker." << endl; }
 }
 

Example

class TradesPerson 
{
    public:
        virtual void sayHi() { cout << "Hi from on top." << endl; }
};
class Tinker : public TradesPerson 
{
    public:
        
};

class Tailor : public TradesPerson 
{
    public:
        virtual void sayHi() { cout << "Hi, I tailor." << endl;}
};


TradesPerson *tr = new Tinker;
tr -> sayHi();                 // output   Hi from on top

tr = new Tailor;
tr -> sayHi();                 // output   Hi, I tailor.

Vtable

class B 
{
   public:
      virtual void m1() { ...... }   // 1st virtual method
      virtual void m2() { ...... }   // 2nd virtual method
};

class D : public B 
{
   public:
      virtual void m1() { ...... }   // overrides 1rst virtual method
};


Constructors and Destructors

Example

class Base 
{
    public:
        Base()  { cout << "Base Constructor" << endl; }
        ~Base() { cout << "Base Destructor" << endl; }
};

class Derived : public Base
{
    public:
        Derived()  { cout << "Derived Constructor" << endl;}
        ~Derived() { cout << "Derived Destructor"<< endl;}
};

int main(){
    Base *obj = new Derived();
    delete obj;
    system("pause");
    return 0;
}

Output
---------
Base Constructor
Derived Constructor
Base Destructor

Problem if derived class dynamically allocates memory it's destructor never gets called. Solution make destructor virtual.

class Base 
{
    public:
        Base()          { cout << "Base Constructor"  << endl; }
        virtual ~Base() { cout  << "Base Destructor"  << endl; }
};

class Derived : public Base
{
    public:
        Derived()  { cout  << "Derived Constructor"  << endl; }
        ~Derived() { cout  << "Derived Destructor"  << endl; }
};

int main(){
    Base *obj = new Derived();
    delete obj;
    system("pause");
    return 0;
}

Output
-------
Base Constructor
Derived Constructor
Derived Destructor
Base Destructor

See destruct1.cpp, destruct2.cpp, destruct3.cpp


Abstract Base Classes.

class Employee
{
	public:
	  virtual void pay() = 0;
};

Employee emp;    // error cannot be instantiated
class Employee
{
        private:
            string name;
            string id;
            string phone;
        public:
            Employee(string n, string i, string p) :
                name(n), id(i), phone(p) {}
            Employee() {}
            
            string getName()  const { return name; }
            string getId()    const { return id; }
            string getPhone() const { return phone; }           
            
            void setName(string n)    { name = n; }
            void setId(string i)      { id = i; }
            void setPhone (string p ) { phone = p; }
            
            virtual ~Employee() {}
            virtual double pay() = 0;
};

class HourlyEmployee : public Employee 
{
        private:
            double rate;
            double hrs;
        public:
            HourlyEmployee(string n, string i, string p, double r, double h) :
                Employee(n,i,p), rate(r), hrs(h) {}
            HourlyEmployee () {}
            
            virtual double pay() { return rate * hrs; }
};
HourlyEmployee emp1("Rita","111","5553434", 25, 20);
cout << emp1.getName() << emp1.pay() << endl;

Employee *emp2 = new HourlyEmployee("Tom","123","5551212", 15, 10);    
cout << emp2 -> getName() << emp2 -> pay() << endl; 

See payday1.cpp and payday2.cpp


STL multimap Class

Creating a multimap

Consider keeping track of words and the line numbers they appear on.

#include <map>

using namespace std;

multimap<string, int> index;

Inserting Elements into a multimap

index.insert(make_pair("transform" , 56));
index.insert(make_pair("transform" , 121));
index.insert(make_pair("transform" , 141));

index.insert(make_pair("virtual", 56));
index.insert(make_pair("virtual", 59));

Traversing a multimap

for(multimap<string, int>::iterator it = index.begin(); it != index.end(); ++it){
        cout << it -> first << " " << it -> second << endl;
}

Finding values based on key.

(Method 1)

int countKey  = index.count("transform");
multimap<string, int>::iterator itKey = index.find("transform");

for(int i = 0; i != countKey; ++i, ++itKey){
        cout << itKey -> second << " " << endl;
}

(Method 2)

multimap<string, int>::iterator beg = index.lower_bound("transform");
multimap<string, int>::iterator end = index.upper_bound("transform");

for(; beg != end; beg++){
        cout << beg -> second << " " << endl;
}

Remove

index.erase("transform");
multimap<string, int>::iterator beg, end;
beg = index.lower_bound("transform");
end = index.upper_bound("transform");

for(; beg != end; beg++){
    if(beg -> second == 121){
      index.erase(beg);            
    }
}