深度探索C++对象模型笔记(五)

Semantics of Construction,Destruction,and copy

考虑如下abstract base class声明:
class Abstract_base
{
public:
virtual ~Abstract_base() = 0;
virtual void interface() const = 0;
virtual const char* mumble() const
{
return _mumble;
}
protected:
char* _mumble;
};
虽然这个class被设计为一个抽象的base class(其中有纯虚函数,不可能拥有实体),但它仍然需要一个明确的构造函数以初始化其data member _mumble。

纯虚拟函数的存在

我们可以静态调用一个纯虚函数(如Abstract_base::interface())。

关于纯虚析构函数,因为每一个派生类的析构函数会被编译器扩展,以静态的方式调用每一个虚基类以及上一层基类的析构函数,因此只要缺乏任何一个基类析构函数的定义,就会导致链接失败。一个比较好的方案是,不要将虚析构函数声明为纯虚。

虚拟规格的存在

如果将Abstract_base::mumble()设计为一个虚函数,那将是一个糟糕的设计。因为它几乎不会被后继派生类改写。一般而言,把所有的成员函数声明为虚函数,然后由编译器的优化操作把非必要的virtual invocation去除,并不是好的设计观念。

虚拟规则中const的存在

决定一个virtual function是否需要const,是一件琐屑的事情。当你面对一个abstract base class时,却不容易做决定,声明一个函数为const,然后才发现其派生类必须修改一个data member。简单的做法是,不用const就是了。

重新考虑class的声明

class Abstract_base
{
public:
virtual ~Abstract_base();
virtual void interface() const = 0;
const char* mumble() const
{
return _mumble;
}
protected:
Abstract_base(char *pc = 0);//新增一个带唯一参数的构造函数
char* _mumble;
};

1、“无继承”情况下的对象构造
对比无继承情况下Point结构体和class(添加默认构造函数)trivial 类函数(构造,析构,拷贝)的情况,可复习此前的笔记即可。
2、继承体系下的对象构造
(略)

vptr初始化

如果在集成体系中每一个constructor内调用一个virtual函数,那么每一次调用的都是什么函数呢?C++规则告诉我们,在Point3d constructor中调用的size()(virtual函数),必须为Point3d::size(),即由构造函数(析构函数)中的对象调用一个virtual function,其函数实体应该是在此class中有作用的那个。由于构造顺序是:由根源末端(bottom up),由内而外,base class constructor执行时,derived实体还没有构造出来。因此如果调用操作必须在constructor和destructor中直接调用,那么将每一个调用操作以静态方式决议之,千万不要用到虚拟机制。另一种方法是在constructor和destructor内设置一个标志,以标志确定是否以静态调用方式进行。

vptr在constructor中应该在何时被初始化,我们有三种选择:

  1. 在任何操作之前
  2. 在base class constructors调用操作之后,但是在程序员的代码或者是member initialization list中所列的members被初始化之前
  3. 在每一件事情发生之后
答案是2。

3、Object copy Semantics

当我们以一个class object指定给另一个class object时,我们有三种选择:

  1. 什么都不做,因此得以实施默认行为
  2. 提供一个explicit copy assignment operator
  3. 明确的拒绝把一个class object指定给另一个class object
如果选择第三点,那么只要将copy assignment operator声明为private,并且不提供定义即可。
余下部分内容前面笔记有记录,主要是在什么情况在位拷贝会无效,虚拟继承部分不做记录
专家建议:不要在任何virtual base class 中声明数据
4、Semantics of Destruction
若class未定义destructor,那么只有在class内的member object或者是base class拥有destructor的情况下,编译器才会合成出一个否则就算class拥有virtual function,也不会合成。
为了决定class是否需要程序层面的destructor或是constructor,想想一个class的生命在哪里结束或开始,需要什么操作才能保证对象的完整?这也是constructor和destructor什么时候起作用的关键。例如:对象在使用前必须初始化为某些特定值,这时候需要一个constructor,当我们明确的delete一个对象时,如果没有理由先将其内容清除干净,也不需要归还任何资源,那么不一定需要一个destructor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值