1.什么是多态?
谈到多态,我们必须首先了解一下什么是虚函数。
虚函数:在类的成员函数前加virtual关键字,把这个成员函数称为虚函数。
多态需满足两个条件:
子类的虚函数须覆盖(重写)父类的虚函数;(协变例外)
当使用基类的指针或引用调用重写的虚函数时,指向基类对象就调用基类的虚函数,指向派生类的对象就调用派生类的虚函数。
注:多态只与对象有关,与类型无关。
扩充:
虚函数重写(覆盖):
当派生类中定义的虚函数和基类中定义的虚函数完全相同的时候,则称派生类中的虚函数重写了基类中的虚函数。
协变:
class A
{
public:
virtual A* func()---virtual A& func()
{
return this;---return *this;
}
};
class B
{
public:
virtual B* func()---virtual B& func()
{
return this;---return *this;
}
};
2.多态的对象模型
单一继承模型
typedef void(*FUNC) ();
class First
{
public:
First()
:_f(1){}
virtual void f(){ cout << "First::f()" << endl; }
virtual void f1(){ cout << "First::f1()" << endl; }
public:
int _f;
};
class Second : public First
{
public:
Second()
:_s(2){}
virtual void f(){ cout << "Second::f()" << endl; }
virtual void f2(){ cout << "Second::f2()" << endl; }
virtual void f3(){ cout << "Second::f3()" << endl; }
public:
int _s;
};
void Print(int *Vfptr)
{
cout << "虚表地址" << Vfptr << endl;
for (int i = 0; Vfptr[i] != 0; ++i)
{
FUNC f = (FUNC)Vfptr[i];
cout << "[" << i << "]" << endl;
f();
}
cout << endl;
}
int main()
{
First f;
Second s;
int *Vfptr1 = (int*)(*(int*)&f);
int *Vfptr2 = (int*)(*(int*)&s);
Print(Vfptr1);
Print(Vfptr2);
system("pause");
return 0;
}
单一继承总结:
虚函数表一般放在最前面;
成员变量根据会根据继承关系按先后顺序排列;
当有虚函数覆盖时,派生类的虚函数会将虚函数表中的基类虚函数替换;
虚函数表最后一个为0/NULL。
多重继承模型:
class B1
{
public:
B1()
:_b1(1){}
virtual void b(){ cout << "B1::b()" << endl; }
virtual void b1(){ cout << "B1::b1()" << endl; }
public:
int _b1;
};
class B2
{
public:
B2()
:_b2(2){}
virtual void b(){ cout << "B2::b()" << endl; }
virtual void b2(){ cout << "B2::b2()" << endl; }
virtual void b3(){ cout << "B2::b3()" << endl; }
virtual void b4(){ cout << "B2::b4()" << endl; }
public:
int _b2;
};
class D : public B1 , public B2
{
public:
D()
:_d(3){}
virtual void b(){ cout << "D::b()" << endl; }
virtual void b1(){ cout << "D::b1()" << endl; }
virtual void b3(){ cout << "D::b3()" << endl; }
virtual void b5(){ cout << "D::b5()" << endl; }
public:
int _d;
};
typedef void(*FUNC) ();//函数指针
void Print(int *Vfptr)
{
cout << "虚表地址" << Vfptr << endl;
for (int i = 0; Vfptr[i] != 0; ++i)
{
FUNC f = (FUNC)Vfptr[i];
cout << "[" << i << "]" << endl;
f();
}
cout << endl;
}
int main()
{
D d;
int *Vfptr1 = (int*)(*(int*)&d);
//B2的虚函数表在B1虚函数表的下面,跳过B1虚函数才可以打印出B2的虚函数表
int *Vfptr2 = (int*)(*((int*)&d+sizeof(B1)/4));
Print(Vfptr1);
Print(Vfptr2);
system("pause");
return 0;
}
D继承后B1,B2后,D类的实例化对象模型:
在VS2013下的运行结果(打印的虚函数表):
多重继承总结:
派生类会继承每个基类的虚函数表;
派生类的成员函数会放在第一个基类的虚函数表中;
成员变量的存储顺序是按照继承先后顺序存储;
派生类中有和基类中相同的虚函数,基类的虚表会被改变。