多态+多态对象模型
来源:互联网 发布:中国能源研究会 知乎 编辑:程序博客网 时间:2024/06/05 02:26
一:什么是多态。
面向对象语言有三大特点,封装----继承----多态。
今天就讨论一下多态,多态是当使用基类的指针或引用调用重写的虚函数时,当指向父类调用的就是父类的虚函数,当指向子类就是调用子类的虚函数。
多态:多种形态。 多态分为静态多态和动态多态。(实现多态的其中一个条件必须是要把子类给给父类,要构成is-a的关系)
注意:必须是基类的指针或引用调用。不能是父类的对象(因为传对象时,只是临时拷贝,只能拿到成员数据,拿不到成员函数,而传引用或指针就什么都拿到)。
二:多态的对象模型--单继承&多继承
单继承:
#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 ;
}
void Test1 ()
{
Base b1 ;
Derive d1 ;
int* VTable1 = (int*)(*( int*)&b1 );
int* VTable2 = (int*)(*( int*)&d1 );
PrintVTable(VTable1 );
PrintVTable(VTable2 );
}
int main()
{
Test1();
return 0;
}
剖析:
首先通过监视窗口分析
其次通过内存来看:
多继承:
#include <iostream>
using namespace std;
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 func3()
{
cout<<"Derive::func3" <<endl;
}
private :
int d1 ;
};
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 ;
}
void main ()
{
Derive d1 ;
int* VTable = (int*)(*( int*)&d1 );
PrintVTable(VTable );
// Base2虚函数表在对象Base1后面
VTable = (int *)(*((int*)&d1 + sizeof (Base1)/4));
PrintVTable(VTable );
}
可以通过监视窗口与内存分析得知:
所以多继承的时候,子类的虚函数放在了先继承的基类的虚表中
三:多态的对象模型--菱形继承和菱形虚拟继承
#include <iostream>
using namespace std;
class Base
{
public:
virtual void fun1()
{
cout<<"void fun1"<<endl;
}
virtual void fun2()
{
cout<<"void fun2"<<endl;
}
int _a;
};
class Base1:public Base
{
public:
virtual void fun1()
{
cout<<"void fun1"<<endl;
}
virtual void fun3()
{
cout<<"void fun3"<<endl;
}
int _b;
};
class Base2:public Base
{
public:
virtual void fun1()
{
cout<<"void fun1"<<endl;
}
virtual void fun14()
{
cout<<"void fun4"<<endl;
}
int _c;
};
class Derive:public Base1,public Base2
{
public:
virtual void fun1()
{
cout<<"void fun1"<<endl;
}
virtual void fun5()
{
cout<<"void fun5"<<endl;
}
int _d;
};
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 a;
Base1 a1;
Base2 a2;
Derive d1;
int* VTable1 = (int*)(*( int*)&a );
int* VTable2 = (int*)(*( int*)&a1);
int* VTable3 = (int*)(*( int*)&a2);
int* VTable4 = (int*)(*( int*)&d1);
PrintVTable(VTable1 );
PrintVTable(VTable2 );
PrintVTable(VTable3 );
PrintVTable(VTable4 );
return 0;
}
菱形继承成员变量时需要虚继承不然会造成二义性:程序无法跑过编译
所以此时就需要菱形虚拟继承才能结果问题:
代码与源代码相同只是稍微在两个Base类前加一个virtual
分析:菱形虚拟继承
分开来看 先看子类的函数:函数部分与上面一种情况的函数分布相同:
- 多态&多态对象模型
- 多态&多态对象模型
- 多态&多态对象模型
- 多态&多态对象模型
- 多态&多态对象模型
- 多态&多态对象模型
- 多态&多态对象模型
- 多态+多态对象模型
- 多态+多态对象模型
- 多态&多态对象模型
- 多态+多态对象模型
- 多态对象模型
- 【c++】多态&多态对象模型
- 浅谈C++多态&多态对象模型
- C++ 多态&多态对象模型
- 多态&多态的对象模型
- 多态及其对象模型
- 多态的对象模型
- golang make & new
- Android 基类BaseActivity的封装
- DataBinding原理解析
- 利用eclipse中的gradle tasks打包项目
- Mybatis调用存储过程
- 多态+多态对象模型
- 上传EXCEL文件并读取到数据库
- WebSocket 网络通信协议
- Tinker实践:一步步带你集成Tinker,让你的APP也用上热修复,告别重复性更新
- WSWP(用 python写爬虫) 笔记五:并发爬虫
- 【机房】数据源配置
- 正则表达式-Collection-List
- Eclipse快捷键
- nginx同一iP多域名配置方法