一 .多态的概念
多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会
产生出不同的状态。
例子:普通人(成人)买票全价,学生买票半价
代码:
//普通人
class Person
{
public:
virtual void BuyTicket()
{
cout << "全价" << endl;
}
};
class Student : public Person
{
public:
virtual void BuyTicket()
{
cout << "半价" << endl;
}
};
void func(Person& p)//或者Person* p
{
p.BuyTicket();
//指针:p->BuyTicket();
}
int main()
{
Person p;
Student s;
func(p);
func(s);
//打印
//全价
//半价
return 0;
}
二 . 解释上述代码
1.虚函数
虚函数:即被virtual修饰的类成员函数称为虚函数。
(虚函数只在类里才是虚函数,非类成员函数不能加virtual)
virtual void BuyTicket()
{
cout << "全价" << endl;
}
2.虚函数重写
虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的
返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。
(另外基类的virtual必须写,否则不构成多态;子类的virtual可以不用写)
3.多态的条件
另一种多态代码:
class Person
{
public:
virtual void BuyTicket()
{
cout << "全价" << endl;
}
};
class Student : public Person
{
public:
virtual void BuyTicket()
{
cout << "半价" << endl;
}
};
int main()
{
Person p;
Student s;
Person* ptr = &p;
ptr->BuyTicket();//全价
ptr = &s;
ptr->BuyTicket();//半价
return 0;
}
4.虚函数重写的例外
(1)协变:返回值可以不同,但是必须是父子类的指针或引用
class Person
{
public:
virtual Person* BuyTicket()
{
cout << "全价" << endl;
return this;
}
};
class Student : public Person
{
public:
virtual Student BuyTicket()
{
cout << "半价" << endl;
return this;
}
};
(2)析构函数名不同(重点)
class Person {
public:
virtual ~Person() { cout << "~Person()" << endl; }
};
class Student : public Person {
public:
virtual ~Student() { cout << "~Student()" << endl; }
};
int main()
{
Person* p1 = new Person;
Person* p2 = new Student;
delete p1;
delete p2;
//如果不是虚函数重写,p1,p2都只会调用~Person(),会出现内存泄漏的问题
return 0;
}
总结:
普通调用(不构成多态条件都是普通调用):调用函数的类型是谁,就调用此类型对应的函数是。
多态调用:调用指针或引用指向的对象。指向父类则调用父类的函数,指向子类则调用子类的函数。
5.来个题目增加对多态的认识
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;
}
这段代码打印什么?
解释和结果:
三 . 重载、覆盖(重写)、隐藏(重定义)的对比
![](https://i-blog.csdnimg.cn/blog_migrate/60b010c5d552bcbae56b1b02509ebcc9.png)
四 . 抽象类
在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口
类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生
类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。
class Car
{
public:
virtual void Drive() = 0;
};
class Benz :public Car
{
public:
virtual void Drive()
{
cout << "Benz-舒适" << endl;
}
};
class BMW :public Car
{
public:
virtual void Drive()
{
cout << "BMW-操控" << endl;
}
};
void Test()
{
Car* pBenz = new Benz;
pBenz->Drive(); //Benz-舒适
Car* pBMW = new BMW;
pBMW->Drive(); //BMW-操控
}
int main()
{
Test();
return 0;
}