欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++高级编程之对象模型、const、new和delete及其重载讲解

程序员文章站 2022-06-10 18:29:55
1.对象模型:虚指针和虚表:vptr和vtbl 1.虚指针和虚表是存在于底层的东西; 2.子类的对象有父类的成分,当一个类有虚函数的时候,这个对象就有一根指针,带有虚函数的对象的大小等于所有数据所...

1.对象模型:虚指针和虚表:vptr和vtbl

C++高级编程之对象模型、const、new和delete及其重载讲解

1.虚指针和虚表是存在于底层的东西;

2.子类的对象有父类的成分,当一个类有虚函数的时候,这个对象就有一根指针,带有虚函数的对象的大小等于所有数据所占用的空间再加4.如上图所示,b是a的子类,b的数据除了自己定义的m_data3、还包括a类的指针和两个数据。子类除了继承a 的数据还继承父类的虚函数调用权,父类有虚函数,子类一定有虚函数。b类继承了a类的两个虚函数,其中vfunc1被改写;除此之外还定义了自己的函数func2,b一共有3个函数。c也是同理。因此,3个类一共定义8个函数,4个虚函数和4个非虚函数。

3.假设用指针p去调用c类的vfunc1()。则用动态绑定去实现,使用虚指针vptr去vtbl中找相应函数的指针,在找到相应的函数。而不使用静态绑定的形式(call×××)

对于一个powerpoint的实现:

C++高级编程之对象模型、const、new和delete及其重载讲解

调用动作被编译为动态绑定的条件:

1.必须是通过指针调用

2.指针是向上转型

3.调用的是虚函数

2.关于this

C++高级编程之对象模型、const、new和delete及其重载讲解

this是一个指针也是一种观念,这个例子的this指向mydoc的地址。其满足动态绑定的条件,因此在运行过程中触发动态绑定,在调用vs(virtual serialise())函数时,指向子类的vs函数。

3.关于const

C++高级编程之对象模型、const、new和delete及其重载讲解

1.const只能放在成员函数的后头,一般的全局函数是不可以在那个位置加const的。

2.const放在那里的意思是告诉编译器,我这个函数不打算改变数据。不加const的意思是可能会改变data,不保证不改变data。

3.对象调用函数的时候,函数可能是const,也可能不是const。

4.关于new和delete

C++高级编程之对象模型、const、new和delete及其重载讲解

new和delete表达式得工作机理:

例子:

string* sp=new string("hello");
string* arr=new string[10];

第一步:new表达式调用一个名为operator new的标准库函数,该函数分配一块足够大、原始、未命名的内存空间;

第二步:编译器运行相应的构造函数以构造这些对象,并赋初值;

第三步:对象被分配了空间并构造完成,返回一个指向该对象的指针。

delete sp;
delete [] arr;

第一步:对指针所指的数组中的元素执行对应的析构函数;

第二步:编译器调用名为operator delete的标准函数释放内存。

C++高级编程之对象模型、const、new和delete及其重载讲解

C++高级编程之对象模型、const、new和delete及其重载讲解

C++高级编程之对象模型、const、new和delete及其重载讲解

1.应用程序可以再全局作用域定义operator new和operator delete函数,也可以将他们定义为成员函数,当编译器发现一条new或delete函数表达式,将在程序中查找可供调用的operator函数。如果被分配的对象是累类型,则编译器首先在类及其基类的作用域中查找。此时如果该类含有operator new成员或者operator delete成员,相应的表达式将调用这些成员。否则,编译器在全局作用域查找匹配的函数。

2.可以使用作用域运算符令new表达式或者delete表达式忽略定义在类中的函数,直接执行全局作用域中的版本。如:::new只在全局作用域中查找匹配的operator new函数,::delete与之类似。

3.标准库定义了operator new和operator delete函数的8个重载版本,其中前4个可能抛出bad_alloc异常,后四个则不会。

可能抛出异常的版本:

void *operator new(size_t); void *operator new[] (size_t); void *operator delete (void*) noexcept; void *operator delete[] (void*) noexcept;

不会抛出异常的版本:

void *operator new(size_t,nothrow_t&) noexcept;
void *operator new[] (size_t,nothrow_t&) noexcept;
void *operator delete (void*, nothrow_t&) noexcept;
void *operator delete[] (void*,nothrow_t&) noexcept;

应用程序可以自定义上边函数版本中的任意一个,但是自定义的版本必须位于全局作用域或者类作用域中。

对于operator new或者operator new[]来说,其返回值类型必须void*。

对于operator delete或者operator delete[]来说,其返回值类型必须void。