1. 多态的概念
1.1 概念
多态的概念:
通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态
2. 多态的定义及实现
2.1多态的构成条件
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。
那么在继承中要构成多态还有两个条件:
- 必须通过
基类的指针
或者引
用调用虚函数- 被调用的函数必须是虚函数,且派生类必须对基类的
虚函数进行重写
2.2 虚函数
虚函数:即被virtual修饰的类成员函数称为虚函数。
只有成员函数才可以加virtual
class Person {
public:
virtual void BuyTicket() {
cout << "买票-全价" << endl;}
};
2.3虚函数的重写
虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数
三同
:返回值类型、函数名字、参数列表完全相同
class Person
{
public:
virtual void BuyTicket() {
cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
// 虚函数重写/覆盖条件 : 虚函数 + 三同(函数名、参数、返回值)
// 不符合重写,就是隐藏关系
// 特例1:子类虚函数不加virtual,依旧构成重写 (实际最好加上)
virtual void BuyTicket() {
cout << "买票-半价" << endl; }
};
class Soldier : public Person{
public:
virtual void BuyTicket() {
cout << "优先买票" << endl; }
};
// 多态两个条件:
// 1、虚函数重写
// 2、父类指针或者引用去调用虚函数
void Func(Person& p)
{
p.BuyTicket();
}
int main()
{
//定义
Person ps;
Student st;
Soldier sd;
//多态——调用了三个不同的函数
Func(ps);
Func(st);
Func(sd);
return 0;
}
结果可看出,不同身份的人去买票结果不同,这就构成了多态
注意
:不是父类的指针或者引用调用就不会构成多态
// 1、不是父类的指针或者引用调用
class Person
{
public:
virtual void BuyTicket() {
cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
// 虚函数重写/覆盖条件 : 虚函数 + 三同(函数名、参数、返回值)
// 不符合重写,就是隐藏关系
// 特例1:子类虚函数不加virtual,依旧构成重写 (实际最好加上)
virtual void BuyTicket() {
cout << "买票-半价" << endl; }
};
class Soldier : public Person{
public:
virtual void BuyTicket() {
cout << "优先买票" << endl; }
};
// 多态两个条件:
// 1、虚函数重写
// 2、父类指针或者引用去调用虚函数
//这里不是父类的指针或引用
void Func(Person p)
{
p.BuyTicket();
}
int main()
{
Person ps;
Student st;
Soldier sd;
//不会构成多态
Func(ps);
Func(st);
Func(sd);
return 0;
}
虚函数重写的例外:
特例1:子类虚函数不加virtual,依旧构成重写 (实际最好加上)
// 2、不符合重写 -- virtual函数
// ps:特例1:子类虚函数不加virtual,依旧构成重写 (实际最好加上)
class Person
{
public:
void BuyTicket() {
cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
// 虚函数重写/覆盖条件 : 虚函数 + 三同(函数名、参数、返回值)
// 不符合重写,就是隐藏关系
// 特例1:子类虚函数不加virtual,依旧构成重写 (实际最好加上)
virtual void BuyTicket() {
cout << "买票-半价" << endl; }
};
class Soldier : public Person{
public:
virtual void BuyTicket() {
cout << "优先买票" << endl; }
};
// 多态两个条件:
// 1、虚函数重写
// 2、父类指针或者引用去调用虚函数
void Func(Person& p)
{
p.BuyTicket();
}
int main()
{
Person ps;
Student st;
Soldier sd;
Func(ps);
Func(st);
Func(sd);
return 0;
}
注意:只要父类没有构成虚函数就不能形成多态。
子类是可以不写virtual的,但是父类必须写
// 2、不符合重写 -- 参数不同
class Person
{
public:
//virtual void BuyTicket(char) { cout << "买票-全价" << endl; }
virtual void BuyTicket(int) {
cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
// 虚函数重写/覆盖条件 : 虚函数 + 三同(函数名、参数、返回值)
// 不符合重写,就是隐藏关系
// 特例1:子类虚函数不加virtual,依旧构成重写 (实际最好加上)
virtual void BuyTicket(int) {
cout << "买票-半价" << endl; }
};
class Soldier : public Person{
public:
virtual void BuyTicket() {
cout << "优先买票" << endl; }
};
// 多态两个条件:
// 1、虚函数重写
// 2、父类指针或者引用去调用虚函数
void Func(Person& p)
{
p.BuyTicket(1);
}
int main()
{
Person ps;
Student st;
Soldier sd;
Func(ps);
Func(st);
//Func(sd);
return 0;
}
特例2:重写的协变(基类与派生类虚函数返回值类型不同)。
返回值可以不同,但要求必须是父子关系的的指针或者引用
父是父类指针,子是子类指针,不然也不是协变
class A{
}