OOP: An Overview
The key ideas in object-oriented programming are data abstraction, inheritance, and dynamic binding.
data abstraction
Inheritance
Classes related by inheritance form a hierarchy. Typically there is a base class at the root of the hierarchy, from which the other classes inherit. These inheriting classes are known as derived classes.
In C++, a base class distinguishes functions that are type dependent from those that it expects its derived classes to inherit without change. The base class defines as virtual those functions it expects its derived classes to define for themselves.
class Quote {
public:
std::string isbn() const;
virtual double net_price(std::size_t n) const;
};
A derived class must specify the class(es) from which it intends to inherit. It does so in a class derivation list, which is a colon followed by a comma-separated list of base classes each of which may have an optional access specifier:
class Bulk_quote : public Quote { // Bulk_quote inherits from Quote
public:
double net_price(std::size_t) const override;
};
A derived class must include in its own class body a declaration of all the virtual functions it intends to define for itself.
Note: A derived class may include the virtual keyword on these functions but is not required to do so.
Dynamic Binding
// calculate and print the price for the given number of copies, applying any discounts
double print_total(ostream &os,
const Quote &item, size_t n)
{
// depending on the type of the object bound to the item parameter
// calls either Quote::net_price or Bulk_quote::net_price
double ret = item.net_price(n);
os << "ISBN: " << item.isbn() // calls Quote::isbn
<< " # sold: " << n << " total due: " << ret << endl;
return ret;
}
Note:
1. the item parameter is a reference to Quote, we can call this function on either a Quote object or Bulk_quote object.
2. because net_price is a virtual function, and because print_total calls net_price through a reference, the version of net_price that is run will depend on the type of the object that we pass to print_total.
// basic has type Quote; bulk has type Bulk_quote
print_total(cout, basic, 20); // calls Quote version of net_price
print_total(cout, bulk, 20); // calls Bulk_quote version of net_price
Because the decision as to which version to run depends on the type of the argument, that decision can’t be made until run time. Therefore, dynamic binding is sometimes known as run-time binding.
Note: In C++, dynamic binding happens when a virtual function is called through a reference (or a pointer) to a base class.