一、多态的概念
概念:通俗的说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
1.2例
#include<iostream>
using namespace std;
class Person {
public:
virtual void BuyTicket() { cout << "买票,全价" << endl; }
};
class Student :public Person {
public:
virtual void BuyTicket() { cout << "买票,半价" << endl; }
/*注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写*/
//void BuyTicket() { cout << "买票,半价" << endl; }
};
void Func(Person& p)
{
p.BuyTicket();
}
int main()
{
Person ps;
Student st;
Func(ps);
Func(st);
return 0;
}
#include<iostream>
using namespace std;
class Person {
public:
virtual void BuyTicket() { cout << "Person买票,全价" << endl; }
};
class Student :public Person {
public:
virtual void BuyTicket() { cout << "Student买票,半价" << endl; }
/*注意:在重写基类虚函数时,派生类的虚函数在不加virtual关键字时,虽然也可以构成重写*/
//void BuyTicket() { cout << "买票,半价" << endl; }
};
void Func(Person p)
{
p.BuyTicket();
}
int main()
{
Person ps;
Student st;
Func(ps);
Func(st);
return 0;
}
二、多态的条件
1. 虚函数重写
2. 父类的指针或者引用去调用虚函数
**注意:**这里的virtual和虚继承里的virtual没有关系。
**3.**虚函数重写:
继承关系父子的两个虚函数,三同(函数名/参数/返回值)
virtual只能修饰成员函数
父类必须加virtual,子类可以不加virtual。即派生类重写的虚函数函数可以不加virtual。
三同存在例外:协变——》返回值可以不同,但是必须是父子类关系的指针或者引用
协变:
class Person {
public:
virtual Person* BuyTicket()
{
cout << "Person买票,全价" << endl;
return nullptr;
}
};
class Student :public Person {
public:
virtual Student* BuyTicket()
{
cout << "Student买票,半价" << endl;
return nullptr;
}
//void BuyTicket() { cout << "买票,半价" << endl; }
};
二
class Person {
public:
virtual Person* BuyTicket()
{
cout << "Person买票,全价" << endl;
return nullptr;
}
~Person()
{
cout << "~Person()" << endl;
}
};
class Student :public Person {
public:
Student* BuyTicket()
{
cout << "Student买票,半价" << endl;
return nullptr;
}
~Student()
{
cout << "~Student()" << endl;
}
};
int main()
{
Person* p = new Person();
delete p;//父类对象调用父类的析构
p = new Student;
delete p;
return 0;
}
为何delete p会调用父类的析构函数?
答:因为派生类的析构和基类的析构构成隐藏关系,因为它们的函数名被处理成了destructor()。先调用destructor(),再调用operator delete§。
class Person {
public:
virtual Person* BuyTicket()
{
cout << "Person买票,全价" << endl;
return nullptr;
}
virtual ~Person()
{
cout << "~Person()" << endl;
}
};
class Student :public Person {
public:
Student* BuyTicket()
{
cout << "Student买票,半价" << endl;
return nullptr;
}
virtual ~Student()
{
cout << "~Student()" << endl;
}
};
int main()
{
Person* p = new Person();
//p->destructor()+operator delete(p)
delete p;//父类对象调用父类的析构
p = new Student;
//p->destructor()+operator delete(p)
delete p;
return 0;
}
同理,这里子类的析构函数也可以不用写virtual关键字。方便了一部分人