随笔分类 -  深入探索C++对象模型

摘要:对象数组的构造:对象数据的构造一般有两种方式:静态和动态(1)静态分配 以string类为例,string a[10];就是以静态形式构造数据,这样的数组的个数是确定的不能修改的。 像这样的数组怎么进行构造和析构呢? 编译器在构造数组的时候会生成一个使用默认构造函数的数组构造函数arr_new(char *p,sizeof(string),int num,构造函数地址,析构函数地址);同样也会生成数组析构函数,形式类似。arr_del(char *p,sizeof(string),int num,析构函数地址); 若数组构造中间出现异常,该函数必须保证已构造的对象析构,然后释放内存。 ... 阅读全文
posted @ 2012-12-21 16:15 我不是geek 阅读(741) 评论(0) 推荐(0)
摘要:虚拟继承下的对象构造:由于虚拟基类对象在子类中只能保持一个实例,那么,子类构造的时候调用父类的构造函数的时候必须保证虚拟基类对象不能够重复构造。那么,C++规定虚拟基类对象的构造只能是最外层的子类进行构造,浅层次的子类将不会在进行构造,保证了虚拟基类对象的唯一性。在虚拟继承体系下,子类的构造函数中必须做一个判断,设置一个标准位,用来判断虚拟基类对象是否已经构建,然后将该标志为传递给浅层次的子类,那么虚拟基类将不会再次构造。例如,编译器会为子类构造函数内部设置标志位Point3D::Point3D(Point3D *this,bool _most_derived){ if(_most_deri. 阅读全文
posted @ 2012-12-21 13:15 我不是geek 阅读(839) 评论(0) 推荐(0)
摘要:类中函数的深度探索类中包含的函数主要有三种:static成员函数、nostatic成员函数、virtual成员函数。C++类中数据成员和成员函数的命名机制:数据成员的命名:在每个数据成员命名的时候编译器将该成员所属的类名也添加上,用来标志这个成员的来源范围。这样,继承类就可以与子类用相同的名字命名其成员,这样就不会产生二义性和冲突,但是对外界而言,通过继承类对象访问该名字,只会获取继承类的数据成员,因为根据命名查找机制,两个名字属于不同的作用域,继承类中的成员覆盖了子类中的成员,想要调用必须显示调用子类成员或在继承类作用域中使用using。(函数名相同)成员函数的命名:在同一个类中允许函数重载 阅读全文
posted @ 2012-12-20 16:58 我不是geek 阅读(987) 评论(0) 推荐(0)
摘要:在学习完类对象的构造后,下面就需要学习类数据成员和函数成员的存取。编译器对于类对象的处理方式:(1)对于空类,编译器为该类添加一个char类型的成员,用来唯一标识该类在内存的位置(2)使用对齐机制,当一个类的内存字节数不足4的倍数将自动补充,目的是为了寻址的方便有些编译器对于空类的处理进行了优化处理,仅当该空类被继承的时候,空类对象在子类对象中不占用任何内存,单独空类的大小仍是1个字节,这样可能会避免对齐机制,优化了C++对象模型的内存空间。但是对于非空类,不处理和优化处理对于类对象的内存空间没有任何改变。例如:class A{};class X:public virtual A{};clas 阅读全文
posted @ 2012-12-19 20:15 我不是geek 阅读(1450) 评论(0) 推荐(0)
摘要:上一章讲过了关于类对象内存分布,对于nostatic数据将会放在对象内存空间中,static数据成员和nostatic、static函数成员将不会放在对象内存中,对于虚拟继承和含有虚函数的类来说,将会在对象内存中增加一个虚表指针,指向该类的虚表,其中虚表中将会存放虚函数的地址和虚拟基类的地址。一个类中只含有一个共享虚表(继承基类的虚表也是继承类的虚表,一般继承类的虚函数会存放在第一个基类的虚表中方便提取),对象中可以含有多个虚指针,继承至基类,除了直接虚拟继承的继承类才会产生新的vptr和虚表用于指示虚拟基类的位置。下面是如何构建类对象,即构造函数的深入探索。首先强调两个C++新手容易陷入的误 阅读全文
posted @ 2012-12-18 21:29 我不是geek 阅读(1433) 评论(0) 推荐(0)
摘要:在实际生产中,遇到一个复杂的类,如果能看出这个类的内存模型结构,那么以后的操作基本就没有难度的;所以说,学会分析一个类的内存模型,是每一个C++程序员必须要会的知识。(1)C++类封装和C中的结构体的区别C++的类封装是在C语言中的结构体的基础上构建起来的,C结构体只允许存在数据,而不会存在对数据的操作。C++语言中延承C语言中的结构体,但增加的对数据的操作,即成员函数;类是对结构体的进一步封装,使某些数据成员对外不可见,称为私有成员。类和结构体最大的区别就是:结构体成员均是public类型的。那么,类和结构体的布局成本有没有区别呢?对于只有数据成员的类和结构体在内存的布局是相同的,没有增加成 阅读全文
posted @ 2012-12-18 10:22 我不是geek 阅读(5547) 评论(0) 推荐(1)
摘要:http://blog.csdn.net/daheiantian/article/details/6530318异常的基本语法1. 抛出和捕获异常 很简单,抛出异常用throw,捕获用try……catch。 捕获异常时的注意事项: 1. catch子句中的异常说明符必须是完全类型,不可以为前置声明,因为你的异常处理中常常要访问异常类的成员。例外:只有你的catch子句使用指针或者引用接收参数,并且在catch子句内你不访问异常类的成员,那么你的catch子句的异常说明符才可以是前置声明的类型。 2. catch的匹配过程是找最先匹配的,不是最佳匹配。 3. catch的匹配过程中,对类型的要求 阅读全文
posted @ 2012-12-14 23:47 我不是geek 阅读(496) 评论(0) 推荐(0)
摘要:http://www.cnblogs.com/assemble8086/archive/2011/10/02/2198308.html有详细介绍,下面只讲什么时候模板类会实例化以及模板类中成员函数实例化和友元函数的使用。模板类的使用实现了编译时多态性,避免了运行时多态性的消耗(虚指针和虚函数表),但是编译时多态和运行时多态并不冲突,编译时多态是根据传入模板的对象类型实现不同的操作完成,比如继承同一接口的不同类型可以在编译时根据调用接口的队形类型实现多态,而运行时多态则根据虚函数来实现,必须等到运行时才能判断真正运行的接口。当模板类中使用虚函数时,模板实例化的时候必须实例化器虚函数表,一旦虚函数 阅读全文
posted @ 2012-12-14 23:38 我不是geek 阅读(5797) 评论(0) 推荐(0)
摘要:一.多重继承#include <iostream>using namespace std;class Base1{public: Base1(){ cout << "Base1::Base1()" << endl;} virtual ~Base1(){ cout << "Base1::~Base1()" << endl;} virtual void speakClearly(){ cout << "Base1::speakClearly()" << e 阅读全文
posted @ 2012-12-13 10:28 我不是geek 阅读(515) 评论(0) 推荐(0)
摘要:虚函数表对C++了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。这里我们着重看一下这张虚函数表。C++的编译器应该是保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证取到虚函数表的有最高的性能——如果有多层继承或 阅读全文
posted @ 2012-11-12 09:52 我不是geek 阅读(605) 评论(0) 推荐(0)