多态&多态对象模型

时间:2021-09-22 21:55:42

一、什么是多态

1.定义:多态,顾名思义就是”多种形态”。
2.构成多态的两个条件:
1).虚函数的重写。(子类可以不用写virtual,但父类必须写virtual,一般最好子类和父类都加virtual)
2).父类的指针(或引用)调用虚函数。
3.虚函数的作用主要就是实现多态,简单的说父类的指针或引用调用重写的虚函数的时候,当父类指针或者引用指向父类对象时调用的是父类的虚函数,指向子类对象时调用的是子类的虚函数。
4.虚函数重写后是就有自己相对应的虚函数表,虚函数表是通过一块连续内存来存储虚函数的地址的。虚函数表解决了继承,虚继承的问题。
注:可以构成多态的特例:
**协变也可构成多态。
**把基类的析构函数定义为虚函数,构成多态,调子类和父类的析构函数。
**友元函数不能被继承,静态成员会被继承。

二、多态的对象模型–单继承&多继承

单继承:子类有且只有一个直接父类。

例子:

 #include<iostream>
using namespace std;

class Base
{
public:
virtual void func1()
{
cout<<"Base::func1"<<endl;
}
virtual void func2()
{
cout<<"Base::func2"<<endl;
}

private:
int a;
};

class Derive : public Base
{
public:
virtual void func1()
{
cout<<"Derive::func1()"<<endl;
}
virtual void func3()
{
cout<<"Derive::func3()"<<endl;
}
virtual void func4()
{
cout<<"Derive::func4()"<<endl;
}
private:
int b;
};

typedef void (*FUNC)();

void PrintVTable(int* VTable)
{
cout<<"虚表地址"<<VTable<<endl;
for(int i=0;VTable[i]!=0;i++)
{
printf("第%d个虚函数的地址:0x%x,->",i,VTable[i]);
FUNC f=(FUNC)VTable[i];
f();
}
cout<<endl;
}
int main()
{
Base b1;
Derive d1;

int* VTable1=(int*)(*(int*)&b1);
int* VTable2=(int*)(*(int*)&d1);

PrintVTable(VTable1);
PrintVTable(VTable2);
}

多态&多态对象模型
父类Base的虚表:
多态&多态对象模型
子类Derive的虚表:
多态&多态对象模型

多态&多态对象模型

多继承:一个子类直接继承两个以上的父类。

#include<iostream>
using namespace std;
typedef void(*FUNC)();//定义一个函数指针类型
class Base1
{
public:
virtual void func1()
{
cout<<"Base1::func1()"<<endl;
}
virtual void func2()
{
cout<<"Base1::func2()"<<endl;
}
private:
int b1;
};
class Base2
{
public:
virtual void func1()
{
cout<<"Base2::func1()"<<endl;
}
virtual void func2()
{
cout<<"Base2::func2()"<<endl;
}
private:
int b2;
};
class Derive:public Base1,public Base2
{
public:
virtual void func1()
{
cout<<"Derive::func1()"<<endl;
}
virtual void func2()
{
cout<<"Derive::func2()"<<endl;
}
virtual void func3()
{
cout<<"Derive::func3()"<<endl;
}
private:
int d;
};
void PrintVTable(int* VTable)
{
cout<<"虚表地址"<<VTable<<endl;
for(int i=0;VTable[i]!=0;i++)
{
printf("第%d个虚函数的地址:0x%x,->",i,VTable[i]);
FUNC f=(FUNC)VTable[i];
f();
}
cout<<endl;
}
int main()
{
Derive d;
int* VTable=*((int**)(&d));
//打印第一个虚表,也就是第一个继承的Base1
PrintVTable(VTable);
//Base2的虚表在Base1的后边,因此要给地址+一个Base1的大小
VTable=(int*)(*((int*)&d+sizeof(Base1)/4));
PrintVTable(VTable);//打印第二个虚表
return 0;
}

多重继承中,子类会同时重写多个父类中相同的函数,并且子类将自己的虚函数存放在第一个继承的虚函数表中。子类没有自己的虚表,继承第一个父类的虚表。
多态&多态对象模型
多态&多态对象模型
多态&多态对象模型
多态&多态对象模型

三、多态的对象模型–菱形继承和菱形虚拟继承

1.菱形继承(钻石继承)

多态&多态对象模型
代码实现如下:

#include <iostream>
using namespace std;

class B
{
public:
B()
{
cout << "B" << endl;
}
~B()
{
cout << "~B()" << endl;
}
private:
int b;
};
class C1 :public B
{
public:
C1()
{
cout << "C1()" << endl;
}
~C1()
{
cout << "~C1()" << endl;
}
private:
int c1;
};
class C2 :public B
{
public:
C2()
{
cout << "C2()" << endl;
}
~C2()
{
cout << "~C2()" << endl;
}
private:
int c2;
};
class D :public C1, public C2
{
public:
D()
{
cout << "D()" << endl;
}
~D()
{
cout << "~D()" << endl;
}
private:
int d;
};

int main()
{
cout << sizeof(B) << endl;
cout << sizeof(C1) << endl;
cout << sizeof(C2) << endl;
cout << sizeof(D) << endl;
return 0;
}

运行结果:
多态&多态对象模型
那么如何得到的这个结果,我们在上一篇写到菱形继承的时候已经详细分析过了,这里就不详细说明了,如果想要更深入的理解请参考:http://blog.csdn.net/sakuramyb/article/details/75675079
* 2.菱形虚拟继承*

class Base
{
public:
void virtual Fun1()
{
cout<<"Base::Fun1()"<<endl;
}
void virtual Fun2()
{
cout<<"Base::Fun2()"<<endl;
}
public:
int _b;
};
class Derive1:virtual public Base
{
public:
void virtual Fun1()
{
cout<<"Derive1::Fun1()"<<endl;
}
void virtual Fun3()
{
cout<<"Derive1::Fun3()"<<endl;
}
public:
int _d1;
};
class Derive2:virtual public Base
{
public:
void virtual Fun1()
{
cout<<"Derive2::Fun1()"<<endl;
}
void virtual Fun4()
{
cout<<"Derive2::Fun4()"<<endl;
}
public:
int _d2;
};
class Derive:public Derive1,public Derive2
{
public:
void virtual Fun1()
{
cout<<"Derive::Fun1()"<<endl;//覆盖
}

void virtual Fun5()
{
cout<<"Derive::Fun5()"<<endl;
}
public:
int _d;
};
int main()
{
Derive d;
d._b = 2;
d._d1 = 3;
d._d2 = 4;
d._d = 5;
PrintVTable(*((int*)&d));

}

多态&多态对象模型
内存分配:
多态&多态对象模型
多态&多态对象模型