C++多态
目录
[TOC]
一句话说清楚多态
同一个东西在不同环境下表现出的不同状态。
编译时多态 | 函数重载overload |
---|---|
运行时多态 | 虚函数virtual function |
虚函数
虚函数产生的背景
在之前的章节《C++继承》中我们其实有提到
编译器通过指针访问成员变量时,指针指向哪个对象就用哪个对象的数据
编译器通过指针访问成员函数时,指针属于哪个类的类型,就访问哪个类的函数。
一个父类的指针无法去访问子类的成员函数,而如果使用强制的向下转型,这又是不可靠且不安全的。所以在此背景下,虚函数诞生了。
虚函数的格式
在父类声明virtual
的成员函数。
class A{
public:
virtual void show();
private:
int a;
}
class B :public A{
public :
virtual void show();
private :
int b;
}
然后在类外,分别对这两个虚函数进行定义。
void A::show() {
cout<<a<<endl;
}
void B::show() {
cout<<a<<b<<endl;
}
这样一来,在main
函数中,即使我们是使用A类的指针p指向B类的对象,在调用时,也可以调用到B的show()
函数
A *p = new A(10);
p->show();
//----------------------
p = new B(11,12);
p->show();
上面这一段程序的输出是10;11 12。可以看到,p作为父类的指针,当指向一个子类对象时,成功调用了子类的成员函数,实现了运行时的多态。
关于虚函数,你需要知道这些
virtual
关键字加在哪里?
- 加在声明处(declaration)就够了,定义处(definition)不用加
- 加在父类就可以了,这样子类中具有遮蔽关系的同名函数都会自动成为虚函数。这里区别一下名字遮蔽和多态哈。
- 构造函数不能是虚函数
- 析构函数有时候必须是虚函数(防止内存泄露)
构成多态的条件
- 存在继承关系
- 继承关系中存在覆盖关系的同名虚函数
- 父类指针指向子类对象,调用虚函数
纯虚函数和抽象类
纯虚函数语法
virtual 返回值类型 函数名 (形参)= 0;
纯虚函数只能被继承,不能被定义。包含纯虚函数的类叫抽象类,抽象类无法实例化。
实例
class Line{
public:
Line(float len);
virtual float area() = 0;
protected:
float m_len;
}
Line::Line (float len):m_len(len){};
定义一个抽象类Line
, 其中area()
函数不去做定义。这里我们意识到我们使用的是protected
去标注m_len
,这是因为如果用private
则子类函数无法访问。
class Rectangle :public Line{
public:
Rectangle(float len, float width);
float area();
protected:
float m_width;
}
Rectangle::Rectangle (float len, float width):m_len(len),m_width(width){};
float Rectangle::area(){
return m_len*m_width;
}
用矩形类Rectangle
去继承抽象类Line
,实现area()
的定义。
Line *p = new Rectangle(2.2, 3.5);
cout <<p->area()<< endl;
从而实现Line
类指针调动了子类Rectangle
中的area()
函数。