1.多态
-
多态,即多种状态,在面向对象语言中,接口的多种不同的实现方式即为多态。
-
C++ 多态有两种:静态多态(早绑定)、动态多态(晚绑定)。
-
静态多态是通过函数重载实现的;动态多态是通过虚函数实现的。
-
多态是以封装和继承为基础的。
2.静态多态(早绑定)
函数重载
class A
{
public:
void do(int a);
void do(int a, int b);
};
3.动态绑定(晚绑定)
虚函数:用virtual修饰成员函数,使其成为虚函数;
注意:
-
普通函数(非类成员函数)不能是虚函数
-
静态函数(static)不能是虚函数
-
构造函数不能是虚函数(因为在调用构造函数时,虚表指针并没有在对象的内存空间中,必须要构造函数调用完成后才会形成虚表指针)
-
内联函数不能是表现多态性时的虚函数。
虚函数(virtual)可以是内联函数(inline)吗???
答案:虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联。
理由如下:内联是在发生在编译期间,编译器会自主选择内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。
inline virtual
唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如Base::who()
),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。
动态多态使用
class Shape // 形状类
{
public:
virtual double calcArea()
{
...
}
virtual ~Shape();
};
class Circle : public Shape // 圆形类
{
public:
virtual double calcArea();
...
};
class Rect : public Shape // 矩形类
{
public:
virtual double calcArea();
...
};
int main()
{
Shape * shape1 = new Circle(4.0);
Shape * shape2 = new Rect(5.0, 6.0);
shape1->calcArea(); // 调用圆形类里面的方法
shape2->calcArea(); // 调用矩形类里面的方法
delete shape1;
shape1 = nullptr;
delete shape2;
shape2 = nullptr;
return 0;
}
虚函数可以是内联函数的实例
#include <iostream>
using namespace std;
class Base
{
public:
inline virtual void who()
{
cout << "I am Base\n";
}
virtual ~Base() {}
};
class Derived : public Base
{
public:
inline void who() // 不写inline时隐式内联
{
cout << "I am Derived\n";
}
};
int main()
{
// 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,
// 编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。
Base b;
b.who();
// 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,
// 所以不能为内联。
Base *ptr = new Derived();
ptr->who();
// 因为Base有虚析构函数(virtual ~Base() {}),
//所以 delete 时,会先调用派生类(Derived)析构函数,
//再调用基类(Base)析构函数,防止内存泄漏。
delete ptr;
ptr = nullptr;
system("pause");
return 0;
}