C++学习笔记(11)——虚函数的特性
2008-03-11 22:55
573 查看
本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!
代码如下:
/**//************************************************************************
* 虚函数的应用特性例子
************************************************************************/
#include <iostream.h>
//没有虚函数的类
class CNoVirtual
...{ int x;
public:
CNoVirtual(int nx)...{x=nx;}
void func() const...{}
int GetX() const ...{return x;}
};
//有一个虚函数的类
class COneVirtual
...{ int x;
public:
COneVirtual(int nx)...{x=nx;}
virtual void func() const...{}
int GetX()...{return x;}
};
//有两个虚函数的类
class CTwoCirtuals
...{ int x;
public:
CTwoCirtuals(int nx)...{x=nx;}
virtual void func() const...{}
virtual int GetX() const ...{return x;}
};
void main()
...{ CNoVirtual obj1(100);
COneVirtual obj2(200);
CTwoCirtuals obj3(300);
cout<<"size of types: ";
cout<<"int : "<<sizeof(int)<<endl;
cout<<"CNoVirtual : "<<sizeof(CNoVirtual)<<endl;
cout<<"void* : "<<sizeof(void*)<<endl;
cout<<"COneVirtual : "<<sizeof(COneVirtual)<<endl;
cout<<"CTwoVirtual : "<<sizeof(CTwoCirtuals)<<endl;
}
1. 运行结果:
2. 对象的内存分配情况:
3. 对象的地址及内容:
4. 对象的成员变量的地址及内容:
综上,对象的内存空间分配情况如下:
说明:
从上面的结果可以看到,没有虚函数的类CNoVirtual的大小正好是其成员变量——一个整型数据的大小,而有一个虚函数和两个虚函数的类的大小还要加上一个紧缩的空指针类型的大小。这说明了在包含虚函数的类中,编译系统自动加入了一些表明类型的信息。
当一个类中拥有虚函数时,编译系统将为该类创建一个数组VTABLE。VTABLE数组中的元素是虚函数的地址,且同一虚函数的地址在基类和派生类的VTABLE中相对首位置的偏移是一样的。同时,编译系统还加入了相应的调用虚函数的代码。所有这些都是不需要程序员作的工作,由系统自动完成。在初始化该类对象时,将加入一个指向VTABLE的指针,这个指针一般称为VPTR。一般来说,VPTR位于该类对象的存储单元的最开始部位,如上图所示。
这样,当VPTR被正确的初始化之后,便指向了该对象的VTABLE,从而在对象及其特定的虚函数定义间建立了联系。从虚函数调用的意义上来说,VPTR表明了类型信息,因为它使得调用与类型相符合。
虚函数的应用特性
例:编写三个类:没有虚函数、有一个虚函数、有两个虚函数,在主函数中定义这三个类的对象,分别取这个类所占的内存空间的大小,观察在内存中的分配;代码如下:
/**//************************************************************************
* 虚函数的应用特性例子
************************************************************************/
#include <iostream.h>
//没有虚函数的类
class CNoVirtual
...{ int x;
public:
CNoVirtual(int nx)...{x=nx;}
void func() const...{}
int GetX() const ...{return x;}
};
//有一个虚函数的类
class COneVirtual
...{ int x;
public:
COneVirtual(int nx)...{x=nx;}
virtual void func() const...{}
int GetX()...{return x;}
};
//有两个虚函数的类
class CTwoCirtuals
...{ int x;
public:
CTwoCirtuals(int nx)...{x=nx;}
virtual void func() const...{}
virtual int GetX() const ...{return x;}
};
void main()
...{ CNoVirtual obj1(100);
COneVirtual obj2(200);
CTwoCirtuals obj3(300);
cout<<"size of types: ";
cout<<"int : "<<sizeof(int)<<endl;
cout<<"CNoVirtual : "<<sizeof(CNoVirtual)<<endl;
cout<<"void* : "<<sizeof(void*)<<endl;
cout<<"COneVirtual : "<<sizeof(COneVirtual)<<endl;
cout<<"CTwoVirtual : "<<sizeof(CTwoCirtuals)<<endl;
}
1. 运行结果:
2. 对象的内存分配情况:
3. 对象的地址及内容:
4. 对象的成员变量的地址及内容:
综上,对象的内存空间分配情况如下:
说明:
从上面的结果可以看到,没有虚函数的类CNoVirtual的大小正好是其成员变量——一个整型数据的大小,而有一个虚函数和两个虚函数的类的大小还要加上一个紧缩的空指针类型的大小。这说明了在包含虚函数的类中,编译系统自动加入了一些表明类型的信息。
当一个类中拥有虚函数时,编译系统将为该类创建一个数组VTABLE。VTABLE数组中的元素是虚函数的地址,且同一虚函数的地址在基类和派生类的VTABLE中相对首位置的偏移是一样的。同时,编译系统还加入了相应的调用虚函数的代码。所有这些都是不需要程序员作的工作,由系统自动完成。在初始化该类对象时,将加入一个指向VTABLE的指针,这个指针一般称为VPTR。一般来说,VPTR位于该类对象的存储单元的最开始部位,如上图所示。
这样,当VPTR被正确的初始化之后,便指向了该对象的VTABLE,从而在对象及其特定的虚函数定义间建立了联系。从虚函数调用的意义上来说,VPTR表明了类型信息,因为它使得调用与类型相符合。
相关文章推荐
- C++虚函数和多态学习笔记
- 继承和多态和虚函数——C++学习笔记二
- C++学习笔记(十四)多态原理与虚函数
- C++ 虚函数内存布局学习笔记
- c++ 11 新特性学习
- C++学习笔记——虚函数
- 【C++学习笔记】特殊用途语言特性
- C++学习笔记(十二):类继承、虚函数、纯虚函数、抽象类和嵌套类
- C++ 虚函数内存布局学习笔记
- C++学习笔记--多态、虚函数
- C++学习 - 虚表,虚函数,虚函数表指针学习笔记
- C++学习笔记11:定位new运算符
- C++ 11学习和掌握 ——《深入理解C++ 11:C++11新特性解析和应用》读书笔记(一)
- C++学习笔记(19)——多继承中的虚函数
- C++学习笔记13:类继承和派生、虚函数
- 【学习笔记】C++primer plus 10. 11. 12. 对象
- C++ 学习笔记(一些新特性总结 2)
- 黑马程序员_学习笔记:11) Jdk5.0新特性:增强for循环、可变参数(...)、静态导入、枚举:关键字 enum、自动拆装箱、泛型
- C++ 学习笔记(15)面向对象程序设计(类、继承、虚函数、抽象类、using命令、容器与继承)
- C++虚函数和多态学习笔记