《深度探索C++对象模型》读书笔记(5)

 ***纯虚拟函数***

在设计抽象基类时,需要注意以下几点:
(1)不要将destructor声明为pure virtual function;
如果将destructor声明为pure virtual function,则设计者一定得定义它。因为每一个derived class destructor会被编译器加以扩展,以静态调用得方式调用其“每一个virtual base class”以及“上一层base class”的destructor。
(2)不要将那些函数定义内容并不与类型有关的函数设计为virtual function,因为其几乎不会被后继的derived class改写。
(3)对于其derived class可能修改某一个data member的函数,不应被声明为const。

 

***“无继承”情况下的对象构造***
先定义class Point:
class  Point  {
public:
Point(
float x = 0.0float y = 0.0) : _x(x),_y(y) {}
virtual float z();
protected:
float _x,_y;
}
;

你可不能小看z()这个virtual function给class Point带来的巨大变化。virtual function的引入促使每一个class Point拥有一个vtpr,这样一来,编译器在constructor中添加了对vptr进行初始化的代码,而copy constructor和copy assignment operator也会对vptr进行设定,而不再是原先简单的bitwise操作了。
请看以下的代码:

Point foobar()
{
Point local;
Point 
*heap = new Point;
*heap = local;
delete heap;
return local;
}

将被内部转化为:

Point foobar(Point  & _result)
{
Point local;
local.Point::Point();
Point 
*heap = _new(sizeof(Point));
if(heap != 0)
heap
->Point::Point();
*heap = local;
_result.Point::Point(local);  
// copy constructor的应用
local.Point::~Point();
return;
}

从以上代码的转化可以看出:一般而言,如果你的设计之中有很多函数都需要以传值方式(by value)传回一个local class object,那么提供一个copy constructor就比较合理。

 

***继承体系下的对象构造***
假设class Point3d虚拟继承于class Point,但由于class Point仅存在一份实体,因而class Point3d的constructor需要注意一个问题。
请看下面的继承关系图:

class  Point3d :  virtual   public  Point  { ... } ;
class  Vertex :  virtual   public  Point  { ... } ;
class  Vertex3d :  public  Point3d,  public  Vertex  { ... } ;

通常来说,class Point3d和class Vertex的constructor均需调用Point的constructor,然而,当Point3d和Vertex同为Vertex3d的subobject时,它们对Point constructor的调用操作一定不可以发生,而是交由Vertex3d来完成。
那么如何做到这一点呢?其实只需在constructor中添加一个参数就可以了。例如,class Vertex3d在调用Point3d和Vertex的constructor之前,总是会把参数_most_derived设为false,于是就压制了两个constructors中对Point constructor的调用操作。

//  在virtual base class情况下的constructor扩充内容
Vertex3d *  Vertex3d::Vertex3d(Vertex3d  * this bool  _most_derived,  float  x,  float  y,  float  z)
{
if(_most_derived != false)
this->Point::Point(x,y);

// 在调用上一层base classes的constructor之前设定_most_derived为false
this->Point3d::Point3d(false,x,y,z);
this->Vertex::Vertex(false,x,y,z);

// 设定vptr
// 安插user code

return this;
}

为了控制一个class中有所作用的函数,编译器只要简单地控制住vptr的初始化和设定操作即可。
vptr初始化操作应该如何处理?实际情况是:应该在base class constructors(具体来说,是所有的virtual base classes和上一层的base classes)调用操作之后,但是在程序员供应的码或是“member initialization list中所列的members初始化操作”之前。为什么是这样呢?
如果每一个constructor都一直等待到其base class constructors执行完毕之后才设置其对象的vptr,那么每次它都能够调用正确的virtual function实体。

constructor的执行算法通常如下:
(1)在derived class constructor中,所有virtual base classes的constructor会被调用;
(2)在derived class constructor中,上一层base class的constructor会被调用;
(3)上述完成之后,对象的vptr(s)被初始化,指向相关的virtual table(s);
(4)如果class有member class object,而后者拥有constructor,那么它们会以其声明顺序的相反顺序被调用;
(5)用户所定义的代码。

下面是vptr必须被设定的两种情况:
(1)当一个完整的对象被构造起来时,如果我们声明一个Point对象,Point constructor必须设定其vptr;
(2)当一个subobject constructor调用了一个virtual function(无论是直接调用或间接调用)时。
在明确了哪些情况下vptr必须被设定,我们在声明一个PVertex时,各个vptr不再需要在每一个base class constructor中被设定。解决之道是把constructor分裂为一个完整的object实体和一个subobject实体。在subobject实体中,vptr的设定可以忽略。

如果我们不对Point供应一个copy assignment operator,而光是依赖默认的memberwise copy,编译器通常不会产生出一个实体,除非class不表现出bitwise语意。关于哪些情况class不表现出bitwise语意,请参见读书笔记(2)。
由于在virtual base class的拷贝操作将造成subobject的多重拷贝,并且该问题至今难以解决。因此笔者的建议是:尽量不要允许一个virtual base class的拷贝操作,甚至建议:不要在任何virtual base class中声明数据。

 

***解构语意学***
如果class没有定义destructor,那么只有在class内含的member object(或是class自己的base class)拥有destructor的情况下,编译器才会自动合成出一个来。
其解构顺序与建构顺序正好相反。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《深度探索C++对象模型》是由侯捷所著的一本经典的C++图书,该书于2012年由机械工业出版社出版。本书的主要内容涵盖了C++对象模型的深入解析和探讨。 在书中,作者详细讲解了C++中的对象模型和相关的概念,如类、对象、继承、多态等。作者首先介绍了C++对象模型的基本概念和特点,包括对象的内存布局、虚函数表和虚函数指针等。然后,作者深入探讨了C++中的继承机制和多态性,包括单继承、多继承、虚继承等。作者还详细介绍了虚函数的实现原理和使用方法。 在书中,作者对C++对象模型的实现细节进行了深入的剖析,包括成员变量和成员函数的内存布局、函数指针和成员函数指针的用法等。同时,作者还讨论了C++中的一些高级特性,如模板、内存管理和异常处理等。通过对C++对象模型深度探索,读者可以更好地理解C++的内部机制和原理,提高程序设计和开发能力。 《深度探索C++对象模型》适合具有一定的C++编程基础的读者阅读,尤其是对C++对象模型感兴趣的读者。通过阅读本书,读者可以进一步了解C++的底层实现和运行机制,从而提高自己的编程能力和代码质量。此外,本书还提供了大量的示例代码和实践案例,可以帮助读者更好地理解和应用所学知识。 总之,《深度探索C++对象模型》是一本深入探讨C++对象模型的经典著作,通过对C++的底层实现和内部机制的剖析,帮助读者深入理解C++编程语言,并提高自己的软件开发能力。 ### 回答2: 《深度探索C++对象模型》是由Stanley B. Lippman于1994年所著的一本经典畅销的C++书籍,该书详细介绍了C++对象模型的内部实现细节。 C++对象模型是指C++编译器在处理对象、继承、多态等面向对象特性时所采用的具体实现方式。这本书通过对对象模型的剖析,帮助读者深入理解C++的内部工作原理,从而写出更高效、更可靠的C++代码。 在《深度探索C++对象模型》中,作者首先介绍了对象、虚函数、继承等C++核心概念,然后详细讲解了C++对象模型的构建过程,包括对象布局、成员函数指针、虚函数表等。作者逐步深入地剖析了C++对象模型在内存中的表示方式,解释了为什么C++可以支持如此强大的面向对象特性。 此外,本书还探讨了一些高级主题,如多重继承、虚拟继承、构造函数和析构函数的执行顺序等。对于想要深入学习C++的读者来说,这本书提供了一些宝贵的技术手册和实用的经验。 尽管《深度探索C++对象模型》的出版时间是1994年,但它仍然被广泛认可为学习C++对象模型的经典之作。在2012年时,由于C++的发展和演进,也许一些内容已经有些过时,但很多基本概念和原理仍然适用。 总而言之,《深度探索C++对象模型》是一本值得阅读的C++经典著作,通过深度探索C++对象模型,读者可以更加深入地了解C++的内部工作原理和实现方式,提升自己的开发技能。 ### 回答3: 《深度探索C++对象模型》是一本于2012年出版的书籍。该书的作者Andrews和Sorkin以全面的角度深入探讨了C++对象模型。该书重点介绍了C++中的对象表示、虚函数、继承、多重继承、构造函数、析构函数等内容,以及与之相关的语法、原理和底层实现。 这本书为读者揭示了C++对象模型的奥秘,让人更加深入地理解C++语言中的类和对象。作者通过分析对象布局、虚函数表、虚函数调用、多继承中的数据布局和函数调用等等,解释了C++对象模型的实现机制。 在读者了解C++对象模型的基础上,该书还介绍了如何有效地利用对象模型来提高程序的性能。作者讨论了虚函数的成本以及如何减少虚函数调用的开销,提供了一些优化技巧。此外,书中还对C++的构造函数和析构函数进行了深入的讨论,详细解释了构造函数和析构函数的执行机制和注意事项。 总的来说,《深度探索C++对象模型》是一本深入剖析C++对象模型的重要参考书籍。通过阅读该书,读者可以更加全面地了解C++的类和对象的实现原理,对于理解C++语言的底层机制和优化程序性能具有积极的作用。无论是对于初学者还是有一定C++基础的开发人员来说,该书都是一本值得阅读的重要参考书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值