发新话题
打印

关于C++特色的笔记一

关于C++特色的笔记一

关于C++特色的笔记一

一对象在内存中的分配
    1、虚函数表的概念
     如果在类中由虚函数,编译器会位该类创建一个虚函数表
     虚函数表是一块连续的内存,类的每个成员都占据虚函数表的移行,而且该行中记录着每一个JMP指令的地址,该地址即为每一行的表项,表示虚函数成员在表中的序号
     在32位操作系统中每一个内存地址以4字节表示,在虚函数表头的前四个字节位指向该表头的指针,内放指针变量,而在此即为表象,亦称为指向JMP指令的指针
    2、关于基类,子类的信息在虚函数表中和虚函数表项之间的关系
     1)虚函数表中前部分对应着基类中的虚函数,而后面对应着新定义的虚函数;
     2)父类中虚函数和子类中的虚函数拥有相同的表项
     3)如果虚函数被子类重写,则它对应的表象应该指向子类对象地实现,即指向子类中特定实现的JMP指令
     4)如果未被重写,则他对应的表项应该指向弗雷中特定实现的JMP指令
    3、数据在内存中的分配
      1)按照继承关系,根据先排父类数据成员再排列新增成员
      2)建立对象时,若定义了一个对象指针,它会先指向父类成员,再指向子类成员;
      3)对于类中的函数成员,编辑器会根据数据成员、函数名、成员函数参数表列来将它修饰成统一的符号
      Class A {public: hello (){}
             ......................           
      }   
              A*P=new  A;
              4)修饰后为A#hello(A*pthis)    pthis指的是当前引用此类的对象
               从而实现了成员的全局话,使得在对象分配的内存中不包含类的成员函数信息
              P->hello();
              如果上述函数是非虚方法:编辑器会产生A#hello(A*p)
              如果上述函数是虚方法:编辑器会先从P出发获得虚函数表指针,然后根据HELLO函数的序号获得对应的表项,接下来取出它指向的JMP指令转到实际函数!
一 动态调用
定义:创建并初始化一块内存区域,使它满足某种对象的布局
具体:前4个字节用来指向对象原型类的虚函数表
      后续部分是数据

二 内存分配
1、计算对象所占据的内存大小
分两部分:指向虚函数表的指针位4字节
          对象的数据:由SIZEOF来求解;
既有CLASS A{
             A();~A();
             }
     A实例大小=4+SIZEOF(A)=SIZEOF(DWORD_PTR)+SIZEOF(A);
2、再用NEW分配内存:VOID*P=NEW CHAR[A实例大小];

3、初始化内存块
      设置虚函数表指针P:*(DWORD_PTR*)P=*(DWORD_PTR*)&A();
即通过执行构造函数生成了一个临时的A对象
      初始化内存成员:*(A*)P=A();采用浅拷贝的方式由编译器按照默认拷贝位实现,对于指针类型的成员,尽拷贝本身而不会拷贝它所指向的内容;
调用:((A*)P)->FUNCTION();
释放内存:((A*)P)->~A();DELETE[]P; P=NULL;


三、接口技术
    接口用抽象类表示
    该抽象类中的每个函数都是纯虚函数,不包含任何成员;
    指向接口的指针仅指向一个数函数表指针,不会有任何数据;
    接口的虚函数被复制到子类,由其负责!
    接口技巧:
    通过把类的构造函数声明为私有的防止直接构造其实例
    如果对象是想了某个接口,则对象可以转化为接口指针!
智能指针的实例
#include "stdafx.h"
#include "iostream"
#define TRACE pritf

class refcount
{int crefs;
public:
recount(void){crefs=0;}
~refcount(){TRACE("goddbye(%d)\n",crefs);}
void upcount(void){++crefs;TRACE("计数增加到(%d)\n",crefs);}
void downcount(void)
{if(--crefs==0) delete this;
    else TRACE("计数减少到(%d)\n",crefs);
}
};

class sample : public refcount{
piblic: void dosomething(void){TRACE("做一些事情\n");}
};


temlate<class T> class ptr
{T* p;
public:
  ptr(T*p_):p(p_)//设置内部指针
  {P->upcount();}
~ptr(void){p-.downcount();}
operatorT*(void0{return p;}
T & operator*(void){return *p;}
T* operator->(void){return *p;}
ptr& operator=(ptr<t>&p_)
   {return operator=((T*)p_);}
ptr& operator=(T*p_)
   {p->downcount();
    p=p_;
    p->upcount();
    return*this;
   }
};

int demo()
{ptr<sample> p=new sample;
ptr<sample> p2=new sample;
p=p2;
p->dosomething();
(*p2).dosomething();
((sample*)p)->dosomething();
return 0;
}

TOP

发新话题