封装 -> 可读性
继承 -> 可扩充性
多态 -> 可重用性
多态:指同一名字的事物可以完成不同的功能。
编译时的多态:主要指函数的重载(包括运算符的重载)、对重载函数的调用,在编译时就能根据实参确定应该调用哪个函数,因此叫编译时的多态;
运行时的多态:和继承和虚函数有关。
#include <iostream>
using namespace std;
//基类People
class People{
public:
People(char *name, int age);//声明构造函数
void display();
protected:
char *m_name;
int m_age;
};
//定义构造函数
People::People(char *name, int age): m_name(name), m_age(age){} //构造函数初始化列表
void People::display(){
cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
}
//派生类Teacher
class Teacher: public People{
public:
Teacher(char *name, int age, int salary);
void display();
private:
int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){
cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
}
int main(){
People *p = new People("王志刚", 23);
p -> display();
p = new Teacher("赵宏佳", 45, 8200);
p -> display();
return 0;
}
//运行结果:
王志刚今年23岁了,是个无业游民。
赵宏佳今年45岁了,是个无业游民。
发现:当基类指针p指向派生类Teacher的对象时,虽然使用了Teacher的成因变量,但是却没有使用它的成员函数。
虚函数:让基类指针能够访问派生类的成因函数。
//更改上面的代码,将display()函数声明为虚函数。
#include <iostream>
using namespace std;
//基类People
class People{
public:
People(char *name, int age);//声明构造函数
virtual void display();
protected:
char *m_name;
int m_age;
};
//定义构造函数
People::People(char *name, int age): m_name(name), m_age(age){} //构造函数初始化列表
void People::display(){
cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
}
//派生类Teacher
class Teacher: public People{
public:
Teacher(char *name, int age, int salary);
virtual void display();
private:
int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){
cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
}
int main(){
People *p = new People("王志刚", 23);
p -> display();
p = new Teacher("赵宏佳", 45, 8200);
p -> display();
return 0;
}
//运行结果:
王志刚今年23岁了,是个无业游民。
赵宏佳今年45岁了,是一名教师,每月有8200元的收入。
多态:基类指针可以按照基类的方式来做事,也可以按照派生类的方式来做事,它有多种形态,或者说有多种表现形式,这种现象就是多态。
对象的内存模型是非常干净的,没有包含任何成员函数的信息,编译器是根据什么找到了成员函数? ------> 虚函数表
#include <iostream>
using namespace std;
//基类People
class People{
public:
People(char *name, int age);//声明构造函数
virtual void display();
protected:
char *m_name;
int m_age;
};
//定义构造函数
People::People(char *name, int age): m_name(name), m_age(age){} //构造函数初始化列表
void People::display(){
cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
}
//派生类Teacher
class Teacher: public People{
public:
Teacher(char *name, int age, int salary);
virtual void display();
private:
int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){
cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
}
int main(){
//实例化对象
People p("王志刚", 23);
Teacher t("赵宏佳", 45, 8200);
People &rp = p;
People &rt = t;
rp.display();
rt.display();
return 0;
}
//运行结果:
王志刚今年23岁了,是个无业游民。
赵宏佳今年45岁了,是一名教师,每月有8200元的收入。
由于引用类似于常量,只能在定义的同时初始化,并且以后也要从一而终,不能再引用其他数据,所以本例中一定要定义两个引用变量,
一个用来引用基类对象,一个用来引用派生类对象。
从运行结果可以看出,当基类的引用指代基类对象时,调用的是基类的成员,当基类的引用指代派生类对象时,调用的是派生类的成员。
#include <iostream>
using namespace std;
//军队
class Troops{
public:
virtual void fight(){ cout<<"Strike back!"<<endl; }
};
//陆军
class Army: public Troops{
public:
void fight(){ cout<<"--Army is fighting!"<<endl; }
};
//99A主战坦克
class _99A: public Army{
public:
void fight(){ cout<<"----99A(Tank) is fighting!"<<endl; }
};
//武直10武装直升机
class WZ_10: public Army{
public:
void fight(){ cout<<"----WZ-10(Helicopter) is fighting!"<<endl; }
};
//长剑10巡航导弹
class CJ_10: public Army{
public:
void fight(){ cout<<"----CJ-10(Missile) is fighting!"<<endl; }
};
//空军
class AirForce: public Troops{
public:
void fight(){ cout<<"--AirForce is fighting!"<<endl; }
};
//J-20隐形歼击机
class J_20: public AirForce{
public:
void fight(){ cout<<"----J-20(Fighter Plane) is fighting!"<<endl; }
};
//CH5无人机
class CH_5: public AirForce{
public:
void fight(){ cout<<"----CH-5(UAV) is fighting!"<<endl; }
};
//轰6K轰炸机
class H_6K: public AirForce{
public:
void fight(){ cout<<"----H-6K(Bomber) is fighting!"<<endl; }
};
int main(){
Troops *p = new Troops;
p ->fight();
//陆军
p = new Army;
p ->fight();
p = new _99A;
p -> fight();
p = new WZ_10;
p -> fight();
p = new CJ_10;
p -> fight();
//空军
p = new AirForce;
p -> fight();
p = new J_20;
p -> fight();
p = new CH_5;
p -> fight();
p = new H_6K;
p -> fight();
return 0;
}
//运行结果:
Strike back!
--Army is fighting!
----99A(Tank) is fighting!
----WZ-10(Helicopter) is fighting!
----CJ-10(Missile) is fighting!
--AirForce is fighting!
----J-20(Fighter Plane) is fighting!
----CH-5(UAV) is fighting!
----H-6K(Bomber) is fighting!
原文:https://www.cnblogs.com/xiaobaizzz/p/12333940.html