这个部分,我尽量每天都更新
chapter 23 Objected-oriented Programming :inheritance
Base Classes and Derived Classes
- often , an object of one class is an object of another classes.in C++, class Rectangle can be said to inherit from class quadrilateral, in this context , class Quadrilateral is a base class, and class Rectangle is a derived class.
- because every derived-class object is an object of its base.and one base class can have many derived classes,the set objects represented by a base class typically is arger than the set of objects represented by any of its derived classes.
- inheritance releationship form treelike hierarchical structures.
- to specify that class TwoDimensionShape is derived from the class shape ,class TwoDimensionShape could be defined in C++ as follows:
class TwoDimensionShape:public shape;
- this is an example of public inheritance,the most commonly used form, we also will discuss private inheritance and protected inheritance,with all forms of inheritance , private members of a base class are not accessible directly from that class’s derived classes, but these private base-class members are sti;; inherited (they are still considered parts of the derived classes), with public inheritance,all other basic-class members retained their original member access when they become members of the derived class,through these inherited base-class members , the derived class can manipulate private members of the base class(if these inherited members provide such functionality in the base class).note that friend function is not inherited.
23.3 protected Members
a base class’s public members are accessible within the body of that base class and any where that the program has a handle (i.e a name , reference or pointer) to an object of the that base class or one of the derived class, a base class’s private members are accessible only withon the body of that base class and that friend base.
using protected access offers an intermediate level of protection between public and private access.
23.4.1
代码部分
//CommissionEmployee.h
#pragma once
#ifndef COMMISSION_H
#define COMMISSION_H
#include<string>
using namespace std;
class CommissionEmployee {
public:
//constructor while initialing
CommissionEmployee(const string &, const string &, const string &, double = 0.0, double = 0.0);
//set the first name
void setFirstName(const string &);
//return first name
string getFirstName() const;
//set the last name
void setLastName(const string &);
//get the last name
string getLastName() const;
//set SSN
void setSocialSecruityNumber(const string &);
//get the SSN
string getSocialSecruityNumber() const;
//set gross sales amount;
void setGrossSales(double);
//get gross sales amount
double getGrossSales() const;
//set setCommisionRate
void setCommisionRate(double);
//double getCommisionRate
double getCommisionRate() const;
//earning
double earnings() const;
void print() const;
private:
string firstName;
string lastName;
string socialSecruityNumber;
double grossSales;
double commisionRate;
};
#endif
//CommissionEmployee.cpp
#include<iostream>
#include<string>
#include"CommissionEmployee.h"
using namespace std;
CommissionEmployee::CommissionEmployee(const string &first, const string &last, const string &SSN, double sales, double rate) {
firstName = first;
lastName = last;
socialSecruityNumber = SSN;
setGrossSales(sales);
setCommisionRate(rate);
}
void CommissionEmployee::setFirstName(const string & first) {
firstName = first;
}
void CommissionEmployee::setLastName(const string & last) {
lastName = last;
}
string CommissionEmployee::getFirstName() const {
return firstName;
}
string CommissionEmployee::getLastName() const{
return lastName;
}
void CommissionEmployee::setSocialSecruityNumber(const string &ssn) {
socialSecruityNumber = ssn;
}
string CommissionEmployee::getSocialSecruityNumber() const {
return socialSecruityNumber;
}
void CommissionEmployee::setGrossSales(double sales) {
grossSales = sales;
}
double CommissionEmployee::getGrossSales() const {
return grossSales;
}
void CommissionEmployee::setCommisionRate(double rate) {
commisionRate = (rate > 0.0 && rate < 1.0) ? rate:0.0;
}
double CommissionEmployee::getCommisionRate() const {
return commisionRate;
}
double CommissionEmployee::earnings() const {
return commisionRate * grossSales;
}
void CommissionEmployee::print() const
{
cout << "commission employee: " << firstName << " " << lastName
<< "\nsocial security number: " << socialSecruityNumber
<< "\ngross sales: " << grossSales
<< "\ncommission rate: " << commisionRate << endl;
}
23.4.2 Creating a class without using inheritance.
the code
//BasePlus.h
#pragma once
#ifndef COMMISSION_H
#define COMMISSION_H
#include<string>
using namespace std;
class BasePlusCommissionEmployee {
public:
//constructor while initialing
BasePlusCommissionEmployee(const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0);
//set the first name
void setFirstName(const string &);
//return first name
string getFirstName() const;
//set the last name
void setLastName(const string &);
//get the last name
string getLastName() const;
//set SSN
void setSocialSecruityNumber(const string &);
//get the SSN
string getSocialSecruityNumber() const;
//set gross sales amount;
void setGrossSales(double);
//get gross sales amount
double getGrossSales() const;
//set setCommisionRate
void setCommisionRate(double);
//double getCommisionRate
double getCommisionRate() const;
//earning
double earnings() const;
void print() const;
//set the baseSalary
void BasePlusCommissionEmployee::setBaseSalary(double);
double BasePlusCommissionEmployee::getBaseSalary() const;
private:
string firstName;
string lastName;
string socialSecruityNumber;
double grossSales;
double commisionRate;
double baseSalary;
};
#endif
//Baseplus.cpp
#include<iostream>
#include<string>
#include"BasePlus.h"
using namespace std;
BasePlusCommissionEmployee::BasePlusCommissionEmployee(const string &first, const string &last, const string &SSN, double sales, double rate, double salary) {
firstName = first;
lastName = last;
socialSecruityNumber = SSN;
setGrossSales(sales);
setCommisionRate(rate);
setBaseSalary(salary);
}
void BasePlusCommissionEmployee::setFirstName(const string & first) {
firstName = first;
}
void BasePlusCommissionEmployee::setLastName(const string & last) {
lastName = last;
}
string BasePlusCommissionEmployee::getFirstName() const {
return firstName;
}
string BasePlusCommissionEmployee::getLastName() const {
return lastName;
}
void BasePlusCommissionEmployee::setSocialSecruityNumber(const string &ssn) {
socialSecruityNumber = ssn;
}
string BasePlusCommissionEmployee::getSocialSecruityNumber() const {
return socialSecruityNumber;
}
void BasePlusCommissionEmployee::setGrossSales(double sales) {
grossSales = sales;
}
double BasePlusCommissionEmployee::getGrossSales() const {
return grossSales;
}
void BasePlusCommissionEmployee::setCommisionRate(double rate) {
commisionRate = (rate > 0.0 && rate < 1.0) ? rate : 0.0;
}
double BasePlusCommissionEmployee::getCommisionRate() const {
return commisionRate;
}
double BasePlusCommissionEmployee::earnings() const {
return commisionRate * grossSales + baseSalary;
}
void BasePlusCommissionEmployee::print() const
{
cout << "commission employee: " << firstName << " " << lastName
<< "\nsocial security number: " << socialSecruityNumber
<< "\ngross sales: " << grossSales
<< "\ncommission rate: " << commisionRate << endl;
}
void BasePlusCommissionEmployee::setBaseSalary(double salary) {
baseSalary = (salary<0.0) ? 0.0 : salary;
}
double BasePlusCommissionEmployee::getBaseSalary() const {
return baseSalary;
}
//test.cpp
#include<iostream>
#include<iomanip>
using namespace std;
#include"BasePlus.h"
int main() {
BasePlusCommissionEmployee employee("Bob", "lewis", "333-33-3333", 5000, 0.04, 300);
//set floating-point output formatting
cout << fixed << setprecision(2);
//get commission employee data
cout << "\nFirst information detained by get function: \n"
<< "\nFirst name is " << employee.getFirstName()
<< "\nlast name is " << employee.getLastName()
<< "\nsocial security number is " << employee.getSocialSecruityNumber()
<< "\ngross sales is " << employee.getGrossSales()
<< "\ncommission rate is " << employee.getCommisionRate()
<< "\nbase salary id " << employee.getBaseSalary() << endl << endl;
employee.setBaseSalary(1000);
cout << "\nupdated employee information output by print function: " << endl << endl;
employee.print();
cout << "\n\nemployee's earning: $" << employee.earnings() << endl;
return 0;
}
- in fact , it is boring and a waste of time.
23.4.3creating a commissionEmployee-basePlusCommissionEmployee inheritance.
- now we create and test a new version of class BasePlusCommissionEmployee that derives from class CommissionEmployee
- in this example , a BasePlusCommissionEmployee object is a CommissionEmployee.
- keyword public indicates the type of inheritance, as a derived class(formed with public inheritance) BasePlusCommissionEmployee inherits all the members of class CommissionEmployee,except for the constructor-each class provides its own constructors that are specific to the class.
//CommissionEmployee.h
#pragma once
#ifndef COMMISSION_H
#define COMMISSION_H
#include<string>
using namespace std;
class CommissionEmployee {
public:
//constructor while initialing
CommissionEmployee(const string &, const string &, const string &, double = 0.0, double = 0.0);
//set the first name
void setFirstName(const string &);
//return first name
string getFirstName() const;
//set the last name
void setLastName(const string &);
//get the last name
string getLastName() const;
//set SSN
void setSocialSecruityNumber(const string &);
//get the SSN
string getSocialSecruityNumber() const;
//set gross sales amount;
void setGrossSales(double);
//get gross sales amount
double getGrossSales() const;
//set setCommisionRate
void setCommisionRate(double);
//double getCommisionRate
double getCommisionRate() const;
//earning
double earnings() const;
void print() const;
protected:
string firstName;
string lastName;
string socialSecruityNumber;
double grossSales;
double commisionRate;
};
#endif
#pragma once
//BasePlus.h
#ifndef BASEPLUS_H
#define BASEPLUS_H
#include<string>
using namespace std;
#include"CommissionEmployee.h"
class BasePlusCommissionEmployee :public CommissionEmployee {
public:
//constructor while initialing
BasePlusCommissionEmployee(const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0);
//set the baseSalary
void BasePlusCommissionEmployee::setBaseSalary(double);
//get it
double BasePlusCommissionEmployee::getBaseSalary() const;
//earning
double earnings() const;
private:
double baseSalary;
};
#endif
//CommissionEmployee.cpp
#include<iostream>
#include<string>
#include"CommissionEmployee.h"
using namespace std;
CommissionEmployee::CommissionEmployee(const string &first, const string &last, const string &SSN, double sales, double rate) {
firstName = first;
lastName = last;
socialSecruityNumber = SSN;
setGrossSales(sales);
setCommisionRate(rate);
}
void CommissionEmployee::setFirstName(const string & first) {
firstName = first;
}
void CommissionEmployee::setLastName(const string & last) {
lastName = last;
}
string CommissionEmployee::getFirstName() const {
return firstName;
}
string CommissionEmployee::getLastName() const {
return lastName;
}
void CommissionEmployee::setSocialSecruityNumber(const string &ssn) {
socialSecruityNumber = ssn;
}
string CommissionEmployee::getSocialSecruityNumber() const {
return socialSecruityNumber;
}
void CommissionEmployee::setGrossSales(double sales) {
grossSales = sales;
}
double CommissionEmployee::getGrossSales() const {
return grossSales;
}
void CommissionEmployee::setCommisionRate(double rate) {
commisionRate = (rate > 0.0 && rate < 1.0) ? rate : 0.0;
}
double CommissionEmployee::getCommisionRate() const {
return commisionRate;
}
double CommissionEmployee::earnings() const {
return commisionRate * grossSales;
}
void CommissionEmployee::print() const
{
cout << "commission employee: " << firstName << " " << lastName
<< "\nsocial security number: " << socialSecruityNumber
<< "\ngross sales: " << grossSales
<< "\ncommission rate: " << commisionRate << endl;
}
#include<iostream>
using namespace std;
//BasePlus.cpp
#include"BasePlus.h"
#include"CommissionEmployee.h"
BasePlusCommissionEmployee::BasePlusCommissionEmployee(const string &first, const string &last, const string &SSN, double sales, double rate, double salary)
:CommissionEmployee(first, last, SSN, sales, rate)
{
setBaseSalary(salary);
}
double BasePlusCommissionEmployee::earnings() const {
return commisionRate * grossSales + baseSalary;
}
void BasePlusCommissionEmployee::setBaseSalary(double salary) {
baseSalary = (salary<0.0) ? 0.0 : salary;
}
double BasePlusCommissionEmployee::getBaseSalary() const {
return baseSalary;
}
//test.cpp
#include<iostream>
#include<iomanip>
using namespace std;
#include"BasePlus.h"
int main() {
BasePlusCommissionEmployee employee("Bob", "lewis", "333-33-3333", 5000, 0.04, 300);
//set floating-point output formatting
cout << fixed << setprecision(2);
//get commission employee data
cout << "\nFirst information detained by get function: \n"
<< "\nFirst name is " << employee.getFirstName()
<< "\nlast name is " << employee.getLastName()
<< "\nsocial security number is " << employee.getSocialSecruityNumber()
<< "\ngross sales is " << employee.getGrossSales()
<< "\ncommission rate is " << employee.getCommisionRate()
<< "\nbase salary id " << employee.getBaseSalary() << endl << endl;
employee.setBaseSalary(1000);
cout << "\nupdated employee information output by print function: " << endl << endl;
employee.print();
cout << "\n\nemployee's earning: $" << employee.earnings() << endl;
return 0;
}
- C++ requires a derived-class constructor to call its base-class constructor to initialize the base-class data members that are inherited into the derived class..
- as you can see, C++ regidly enforces restriction on private data members.
- another reason to include the base-class header file is that the compiler uses a class definition to determine the size of an object of that class, a client program that creates an object of an class must #include the class definition to enable the compiler to reverse the proper amount of memory for te object,whenusing inheritance, a derived-class object’s size depends on the data members declared explicitly in its class definitionand the data members.
23.3.4 CommissionEmployee-BasePlusCommissionEmployee inheritance hierarchy using protected Data.
- same as the code above.
- to enable class BasePlusCommissionEmployee to directly access CommissionEmployee data members firstName,lastName and so on , we can declare those members as protected in the base class.as we discussed before , a vase’s classs protected members can be accessed by members and friends of any classes derived from that base class.
- notes on using protected Data.
- in most cases,however , it is better to use private data members to encourage proper software engineering , and leave code optimization issues to the compiler,your code will be easier to maintain ,modify and debug.
- problems.
a derived-class object can assign a negative value to the protected data member,thus leaving the object in an inconsistent state.
23.4.5CommissionEmployee-BasePlusCommissionEmployee inheritance Hierarchy using private Data
- final version
//CommissionEmployee.h
#pragma once
#ifndef COMMISSION_H
#define COMMISSION_H
#include<string>
using namespace std;
class CommissionEmployee {
public:
//constructor while initialing
CommissionEmployee(const string &, const string &, const string &, double = 0.0, double = 0.0);
//set the first name
void setFirstName(const string &);
//return first name
string getFirstName() const;
//set the last name
void setLastName(const string &);
//get the last name
string getLastName() const;
//set SSN
void setSocialSecruityNumber(const string &);
//get the SSN
string getSocialSecruityNumber() const;
//set gross sales amount;
void setGrossSales(double);
//get gross sales amount
double getGrossSales() const;
//set setCommisionRate
void setCommisionRate(double);
//double getCommisionRate
double getCommisionRate() const;
//earning
double earnings() const;
void print() const;
private:
string firstName;
string lastName;
string socialSecruityNumber;
double grossSales;
double commisionRate;
};
#endif
#pragma once
//BasePlus.h
#ifndef BASEPLUS_H
#define BASEPLUS_H
#include<string>
using namespace std;
#include"CommissionEmployee.h"
class BasePlusCommissionEmployee :public CommissionEmployee {
public:
//constructor while initialing
BasePlusCommissionEmployee(const string &, const string &, const string &, double = 0.0, double = 0.0, double = 0.0);
//set the baseSalary
void BasePlusCommissionEmployee::setBaseSalary(double);
//get it
double BasePlusCommissionEmployee::getBaseSalary() const;
//earning
double earnings() const;
private:
double baseSalary;
};
#endif
//CommissionEmployee.cpp
#include<iostream>
#include<string>
#include"CommissionEmployee.h"
using namespace std;
CommissionEmployee::CommissionEmployee(const string &first, const string &last, const string &SSN, double sales, double rate)
:firstName(first),lastName(last),socialSecruityNumber(SSN){
//firstName = first;
//lastName = last;
//socialSecruityNumber = SSN;
setGrossSales(sales);
setCommisionRate(rate);
}
void CommissionEmployee::setFirstName(const string & first) {
firstName = first;
}
void CommissionEmployee::setLastName(const string & last) {
lastName = last;
}
string CommissionEmployee::getFirstName() const {
return firstName;
}
string CommissionEmployee::getLastName() const {
return lastName;
}
void CommissionEmployee::setSocialSecruityNumber(const string &ssn) {
socialSecruityNumber = ssn;
}
string CommissionEmployee::getSocialSecruityNumber() const {
return socialSecruityNumber;
}
void CommissionEmployee::setGrossSales(double sales) {
grossSales = sales;
}
double CommissionEmployee::getGrossSales() const {
return grossSales;
}
void CommissionEmployee::setCommisionRate(double rate) {
commisionRate = (rate > 0.0 && rate < 1.0) ? rate : 0.0;
}
double CommissionEmployee::getCommisionRate() const {
return commisionRate;
}
double CommissionEmployee::earnings() const {
return commisionRate * grossSales;
}
void CommissionEmployee::print() const
{
cout << "commission employee: " << firstName << " " << lastName
<< "\nsocial security number: " << socialSecruityNumber
<< "\ngross sales: " << grossSales
<< "\ncommission rate: " << commisionRate << endl;
}
#include<iostream>
using namespace std;
//BasePlus.cpp
#include"BasePlus.h"
#include"CommissionEmployee.h"
BasePlusCommissionEmployee::BasePlusCommissionEmployee(const string &first, const string &last, const string &SSN, double sales, double rate, double salary)
:CommissionEmployee(first, last, SSN, sales, rate)
{
setBaseSalary(salary);
}
double BasePlusCommissionEmployee::earnings() const {
return CommissionEmployee::earnings() + baseSalary;
}
void BasePlusCommissionEmployee::setBaseSalary(double salary) {
baseSalary = (salary<0.0) ? 0.0 : salary;
}
double BasePlusCommissionEmployee::getBaseSalary() const {
return baseSalary;
}
//test.cpp
#include<iostream>
#include<iomanip>
using namespace std;
#include"BasePlus.h"
int main() {
BasePlusCommissionEmployee employee("Bob", "lewis", "333-33-3333", 5000, 0.04, 300);
//set floating-point output formatting
cout << fixed << setprecision(2);
//get commission employee data
cout << "\nFirst information detained by get function: \n"
<< "\nFirst name is " << employee.getFirstName()
<< "\nlast name is " << employee.getLastName()
<< "\nsocial security number is " << employee.getSocialSecruityNumber()
<< "\ngross sales is " << employee.getGrossSales()
<< "\ncommission rate is " << employee.getCommisionRate()
<< "\nbase salary id " << employee.getBaseSalary() << endl << endl;
employee.setBaseSalary(1000);
cout << "\nupdated employee information output by print function: " << endl << endl;
employee.print();
cout << "\n\nemployee's earning: $" << employee.earnings() << endl;
return 0;
}
chapter 24
24.2 Polymorphism Examples
- With polymorphism , one function can cause different actions to occur , depending on the type of the object on which the function is invoked,this gives the programmer tremendous expressive capability ,
- the polymorphism occurs when a program invokes a virtue function through a base-class pointer or reference - C++ dynamically chooses the correct function for the class from which the object was instantiated ,