class Employee
{
public:
Employee(string n, double s);
string get_name() const;
double get_salary() const;
void set_salary(double s);
virtual double annual_income() const;
void print(ostream& out) const;
private:
string name;
double salary;
};
double Employee::annual_income() const { return get_salary(); }class Manager : public Employee { public: Manager(string n, double s, double b); virtual double annual_income() const; private: double bonus; };
Manager::Manager(string n, double s, double b)
: Employee(n, s), bonus(b) {}
double Manager::annual_income() const
{
return get_salary() + bonus;
}
Employee* emp = new Manager("Sarah Smith", 67000, 2000);
vector<Employee*> department(3);
department[0] = new Manager("Sarah Smith", 67000, 2000);
department[1] = new Employee("Lisa Lim", 36000);
department[2] = new Employee("Harry Hacker", 42000);
for (int i = 0; i < department.size(); i++)
{
cout << "Employee: "
<< department[i]->get_name() << " income "
<< department[i]->annual_income() << "\n";
}
Employee Sarah Smith income 69000
Employee Lisa Lim income 36000
Employee Harry Hacker income 42000
Employee e("Lisa Lim", 36000);
cout << e.annual_income() << "\n"; // Statically bound
Employee* e = new Manager("Sarah Smith", 67000, 2000);
cout << e->get_salary() << "\n";
// Static binding, because get_salary is not virtual
cout << e->annual_income() << "\n";
// Dynamic binding, because annual_income is virtual
void Employee::print(ostream& out) const
{
out << "Name " << get_name()
// Static binding, same as Employee::get_name()
<< " income " << annual_income() << "\n";
// Dynamic binding, same as this->annual_income()
}
ostream& operator<<(ostream& out, const Employee& e)
{
out << "Employee " << e.name();
return out;
}
ostream& operator<<(ostream& out, const Manager& m)
{
out << "Manager " << e.name();
return out;
}
Manager man = new Manager(. . .);
cout << *man << "\n"; // Executes Manager function
void print(ostream& out, Employee& emp)
{
out << emp << "\n";
}
print(cout, *man);
// Will print name as Employee not as Manager
class Employee
{
. . .
virtual void print(ostream& out) const;
};
void Employee::print(ostream& out) const
{
out << "Employee " << name();
}
class Manager : public Employee
{
. . .
virtual void print(ostream& out) const;
};
void Manager::print(ostream& out) const
{
out << "Manager " << name();
}
ostream& operator<<(ostream& out, const Employee& e)
{
e.print(out);
return out;
}
Employee* emp = new Employee("Fred Jones", 67000);prints: Employee Fred Jones.
cout << emp << "\n";
emp = new Manager("Sarah Smith", 82000);prints: Manager Sarah Smith.
cout << emp << "\n";
Syntax 21.1:
Pure Virtual Member Function
class ClassName
{
. . .
virtual return_type function_name(parameters) = 0;
. . .
};
|
Syntax 21.1:
Pure Virtual Member Function (cont.)
|
2 common ways to obtain the dynamic type of an object:
Warning: use virtual methods instead of RTTI and complex conditionals
Syntax 21.2:
Dynamic Cast
dynamic_cast<type_name>(expression)
|
for (int i = 0; i < department.size(); i++)
{
Manager* m = dynamic_cast<Manager*>(department[i]);
if (m != NULL)
cout << "Employee " << department[i]->get_name()
<< " is a manager.\n";
else
cout << "Employee " << department[i]->get_name()
<< " is not a manager.\n";
}
Syntax 21.3:
typeid
typeid(expression) typeid(type_name)
|
will producefor (int i = 0; i < department.size(); i++) cout << typeid(*department[i]).name() << "\n";
Manager
Employee
Employee
for (int i = 0; i < department.size(); i++)
{
if (typeid(*department[i]) == typeid(Manager))
cout << "Employee " << department[i]->get_name()
<< " is a manager. \n";
else
cout << "Employee " << department[i]->get_name()
<< " is not a manager. \n";
}
Employee e("Lisa Lim", 36000);
Manager m("Sarah Smith", 67000, 2000);
e = m; // Permitted, but manager fields sliced away
cout << e.annual_income() << "\n";
// Uses Employee member function
Syntax 21.4:
Multiple Inheritance
class DerivedClassName : public BaseClass1, . . . public BaseClassn
|
TeachingAssistant* fred = new TeachingAssistant();
Employee* new_hire = fred; // Legal, because a TeachingAssistant is-a Employee
Student* advisee = fred; // Legal, because a TeachingAssistant is-a Student
Student* mary = . . .; TeachingAssistant* lab_instructor = dynamic_cast<TeachingAssistant*>(mary); if (lab_instructor != NULL) cout << "Yes, mary is a TeachingAssistant. \n"; else cout << "No, mary is not a TeachingAssistant. \n";
TeachingAssistant* fred = new TeachingAssistant();
cout << "Your number is " << fred->get_id() << "\n";
// Error, ambiguous member function name
cout << "Your teaching assistant is "
<<fred->Employee::get_id() << "\n";
class TeachingAssistant : public Student, public Employee
{
public:
string get_id() const;
string student_id() const;
};
// get_id will return Employee identification number
string TeachingAssistant::get_id()
{
return Employee::get_id();
}
string TeachingAssistant::student_id()
// Make student value available by a different name
{
return Student::get_id();
}
class Person
{
public:
Person(string n);
string get_name() const;
private:
string name;
};
class Employee : public Person
{
. . .
};
class Student : public Person
{
. . .
};
class Student : virtual public Person
{
. . .
};
class Employee : virtual public Person
{
. . .
};
class TeachingAssistant : public Student, public Employee
{
. . .
};
TeachingAssistant* fred = new TeachingAssistant();
Student* s = fred; // Legal, because TeachingAssistantis-a Student
Person* p1 = s;
Employee* e = fred;
Person* p2 = e;
Person* p3 = fred; // Legal if virtual inheritance used, otherwise error
Consider putting a window up on a screen. The concept of window is generic.
class wxWindow
{
public:
. . .
// Pure virtual member function
virtual void OnPaint(wxPaintEvent& event) = 0;
virtual void OnMouseEvent(wxMouseEvent& event);
. . .
};
void wxWindow::OnMouseEvent(wxMouseEvent& event)
{
// Default behavior, do nothing
}
class ClockWindow : public wxWindow
// ClockWindow will be developed in Chapter 27
{
public:
. . .
virtual void OnPaint(wxPaintEvent& event);
virtual void OnMouseEvent(wxMouseEvent& event);
. . .
};
void ClockWindow::OnMouseEvent(wxMouseEvent& event)
{
. . . // Implement mouse events for this specific application
}