多态
分类
编译时多态/早绑定/overload:函数和运算符重载
运行时多态/晚绑定/override:继承与虚函数
覆盖(重写override)与虚函数的使用
覆盖成立的三个条件
1.继承
2.子类覆盖(重写)父类虚函数
3.父类指针/引用指向子类多态产生的效果
同样的调用语句实现不同的表现,框架的基石,设计模式的基础。虚函数定义规则:
1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,有无const
.那么即使加上了virtual
关键字,也是不会覆盖。
2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。
3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。
4.内联(inline
)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义,但是在编译的时候系统仍然将它看做是非内联的。
5.构造函数不能是虚函数,因为构造的时候,对象还是一片未定型的空间,只有构造完成后,对象才是具体类的实例。
6.析构函数可以是虚函数,而且通常声明为虚函数。
子类以
new
方式实例化,指针赋值给父类指针,delete
父类指针时,只调用父类的析构函数,不调用子类的析构函数。
class A{
virtual void test(){}
};
class B:public A{
void test(){}
};
class C:public B{
void test(){}
};
class A{
virtual void test(){}
};
class B:public A{
};
class C:public B{
void test(){}
};
特例
class A{
virtual A* test(){}
};
class B:public A{
B* test(){}
};
构造函数和析构函数是否可以是虚函数?
多态的实现原理分析
当类中声明虚函数时,编译器会在类中生成一个虚函数表(基类和派生类中各自都会生成一个)虚函数表
虚函数表是一个存储类成员函数指针的数据结构
虚函数表是由编译器自动生成和维护的
virtual
函数会被编译器放入虚函数表中
存在虚函数时,每个对象当中都有一个指向虚函数表的指针(vptr指针)纯虚函数
纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加=0
class 类名{
virtual 返回值类型 函数(形参列表) = 0;
}
- 抽象类
包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。
继承抽象类仍然可能是抽象类?
纯虚函数可以写函数体,但是不可能被调用?