1.多态的概念
2.多态的构成条件
多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。在继承中,构成多态需要有两个条件:
2.1 虚函数
2.1.1 虚函数构成重写的三个条件
虚函数的重写也称为覆盖。要求派生类中有一个虚函数与基类完全相同。完全相同指的是三同,返回值相同,参数列表相同,函数名相同。不符合重写的就是隐藏关系。
2.1.2 两个例外
class A{};
class B : public A {};
class Person {
public:
virtual A* f() {return new A;}
};
class Student : public Person {
public:
virtual B* f() {return new B;}
};
(2)析构函数的重写
2.2 重载、重写和重定义
3.抽象类
4.多态的原理
一个含有虚函数的类中会包含一个虚表指针,而虚表指针指向一个个虚函数的地址。看起来是一个虚函数指针数组。一般这个数组最后会放一个空指针。
4.1 派生类的虚表生成
一般是先将基类中的虚表内容拷贝一份到派生类虚表中,如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数,派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。
4.2 静态多态与动态多态
满足了多态的条件的函数调用是在运行中到对象中去寻找的,而不满足多态的会在编译时就确认好。
5.多继承中的虚函数表
多继承派生类的未重写的虚函数放在第一个继承基类部分的虚函数表中。
6.多态常考面试题
(1).以下程序输出结果是什么()
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;
}
A: A->0 B: B->1 C: A->1 D: B->0 E: 编译出错 F: 以上都不正确
答案:B 虚函数重写是接口继承,重写实现,普通函数继承是实现继承。 p是new的B类,而p去调用test时,test里包含着A*的this指针,this指针调用func,func构成重写,满足多态条件,于是实现是类B的func,接口是类A。
(2)inline函数可以是虚函数吗?
答:可以,不过编译器就忽略inline属性,这个函数就不再是inline,因为虚函数要放到虚表中去。