关于C++虚函数多态的剖析
来源:互联网 发布:java动力节点培训坑人 编辑:程序博客网 时间:2024/06/01 08:13
在C++中,多态是通过虚函数来实现的。如下:
//含有纯虚函数的类叫抽象类,抽象类不能被实例化,抽象类的继承类如果不该写纯虚函数,//那么该类仍然是抽象类
class shape
{
public:
virtual void display() = 0;
};
class rect: public shape
{
public:
virtual void display()
{
cout<<"rect"<<endl;
}
};
class circle: public shape
{
public:
virtual void display()
{
cout<<"cricle"<<endl;
}
};
class square: public shape
{
public:
virtual void display()
{
cout<<"square"<<endl;
}
};
int main(int argc, char* argv[])
{
//shape o_shape;
rect o_rect;
circle o_circle;
square o_square;
shape *base_shape[3] = {//&o_shape,
&o_rect,
&o_circle,
&o_square,};
for( int i = 0; i < 3; i++ )
{
base_shape[i]->display();
}
int stop;
cin>>stop;
return 0;
}
会打印:
rect
circle
square
由此可以看到这是以相同的指令调用了不同的函数,这种性质称为多态,编译器无法在编译时期判断到底调用哪个函数,必须在执行期才能判断,这称为动态绑定或者好后期绑定。为什么会这样,下面会通过内存布局来进行说明。
为了达到动态绑定的目的,C++编译器通过某个表格,在执行期间“间接”调用实际上要绑定的函数,这样的表格称为虚函数表(vtable),每一个含有虚函数的类,编译器都会为他做一个虚函数表,表中的每一个元素都指向虚函数地址。此外,为了获取该表,编译器会为类加上一项成员变量,是一个指向该虚函数表的指针(vptr)。
C++中的成员函数,你可以想象他为C语言中的函数,他只是被编译器改过名称,并增加了个this参数,因而可以处理调用者(C++对象)中的成员变量。所以,在一个类的内存区域中,你看不到任何与成员函数有关的东西。
每一个由此类派生出来的对象,都有一个vptr,当我们通过对象调用虚函数时,实际上是通过vptr找到虚函数表,再找出虚函数的真正地址。
奥妙就在这个虚函数表以及虚函数的调用方式,虚函数表是依据虚函数在类中的声明次序,一一填入函数指针,派生类会继承虚函数表(以及所有他可以继承的成员),当在派生类中改写虚函数时,虚函数表就受到了影响,表中的虚函数地址将不是基类虚函数地址,而变成了派生类虚函数地址。
- 关于C++虚函数多态的剖析
- 深入剖析C 重载函数的应用
- 【C++】拷贝构造函数的剖析
- 【C++】多态机制的剖析!!!
- C-main函数剖析。
- c::关于虚函数的一点补充
- 12-4-18关于虚析构函数的剖析
- 关于《C语言深度剖析》之编译器的bug问题
- 关于C语言相关操作符的个人剖析
- 深入剖析C/C++函数的参数传递机制
- 深入剖析C/C++函数的参数传递
- 深入剖析C/C++函数的参数传递机制
- 深入剖析C/C++函数的参数传递机制
- C语言中压栈函数push()的参数剖析
- C语言函数的可变长度参数va_arg剖析
- C编译器剖析_C语言的变参函数
- C语言深度剖析-----函数与指针的分析
- matlab的c程序接口mexFunction函数剖析
- 停止不必要的服务
- 2.1.1.1.1.6.1:简单易用的集成开发环境
- BMP文件格式分析
- C#遍历一个文件夹下的所有文件夹
- NBA联盟08-09赛季年薪榜TOP20:
- 关于C++虚函数多态的剖析
- Flex中如何在mx:Style中用@font-face,在Flash SWF中嵌入字体
- SOAP协议规范介绍
- Ajax,UTF-8还是GB2312. eval 还是execScript
- SQUID工作原理是什么
- 从JAVA到.NET
- 关于WebRequest & SimpleWorkerRequest
- GetWindowRect()和GetClientRect()
- JavaScript 框架开发笔记 [一] 寻找namespace