目录
多态概念
完成某个行为,不同的对象去完成时会产生出不同的状态,称为多态。例如抢红包场景,不同的用户抢到金额大小不一样的红包
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。
继承中要构成多态的条件(两个条件必须同时满足)
1. 派生类必须对基类的虚函数进行重写
(重写的条件是:被调用的函数必须是虚函数、还有函数名,返回值,参数必须相同才能构成虚函数,不符合重写就是隐藏关系,既不构成多态)
重载:两个函数在同一作用域、参数/函数名相同
重写(覆盖):两个函数分别在基类和派生类的作用域、参数/函数名/返回值必须相同、必须是虚函数
重定义(隐藏):函数名相同、两个函数分别在基类和派生类的作用域、不是重写就是重定义
2. 必须通过基类的指针或者引用调用虚函数
不同人买票不同价格:
class Person
{
public:
virtual void BuyTicket()
{
cout << "全价" << endl;
}
};
class Student :public Person
{
public:
virtual void BuyTicket()//虚函数+三同,就是虚函数的重写/覆盖条件
{
cout << "半价" << endl;
}
};
class Soldier :public Person
{
public:
virtual void BuyTicket()
{
cout << "免费" << endl;
}
};
void fun(Person& p)//必须通过基类的指针或者引用调用虚函数
//这时候跟p的类型无关,而是看指针or引用指向的对象
{
p.BuyTicket();
}
![](https://img-blog.csdnimg.cn/1b133992cb234d75b2e619f6e12358e3.png)
多态注意事项
1.只有成员函数才能加virtual,全局函数无法加virtual
2.基类加virtual,子类不加virtual,只要子类符合三同和重写,也符合多态(不要这么做,默认加上)
3.返回值可以不同,但是要求必须是父子关系的指针或者引用(只要属于父子类型的指针或引用都可以,不能颠倒关系),称为协变
![](https://img-blog.csdnimg.cn/440bfb0506794664be005de6949ccaf2.png)
![](https://img-blog.csdnimg.cn/06c9e62aa1794f29a6fc2495be292d05.png)
![](https://img-blog.csdnimg.cn/9961a3fce16541daaa6457a4970883b6.png)
以下程序输出结果是什么?
class A
{
public:
virtual void func(int val = 1) { std::cout << "A->" << val << std::endl; }
virtual void test() { func(); }
};
class B : public A
{
public:
void func(int val = 0) { std::cout << "B->" << val << std::endl; }
};
int main(int argc, char* argv[])
{
B* p = new B;
p->test();
return 0;
}
A: A->0 B: B->1 C: A->1 D: B->0 E: 编译出错 F: 以上都不正确
解答:
首先p->test没有构成多态,A中的test传参A* this调用func,构成多态条件,调用了B类中的func:B->,其中虚函数重写是一个