C/C++编程:无继承情况下的对象构造

2021/5/7 22:25:12

本文主要是介绍C/C++编程:无继承情况下的对象构造,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

结构体

对于下面程序片段
在这里插入图片描述
L1、L2、L6表现出三种不同的对象产生方式:

  • 全局(global)内存配置
  • 本地(local)内存呢配置
  • 堆(heap)内存配置

L7将一个类对象指定给另一个,L10设定返回值,L9则明确以delete运算符删除堆对象

一个对象的生命,是该对象的一个执行期属性:

  • 全局对象的生命和整个程序的生命相同
  • 本地对象的生命从L5的定义开始,到L10结束
  • 堆对象的生命从它被new配置出来开始,到delete销毁为止

下面是Point的第一次声明,可以写成C程序。C++标准说设置一种POD声明形式:

typedef struct{
	float x, y, z:
}Point;

如果我们用C++来编译这段码,会发生什么事?

  • 理论上,编译期会为Point声明一个trivial默认构造函数、一个trivial析构函数、一个trivial拷贝构造函数、一个trivial拷贝赋值运算符
  • 实际上,编译期会分析这个声明,并为它贴上POD标志

当编译期遇到如下定义:

/*(1)*/ Point global;
  • 理论上,Point1的trivial默认构造函数trivial析构函数都会被产生并调用:
    • 构造函数在程序起始处(startup)被调用
    • 析构函数在程序exit()是被调用(exit()是由系统产生,放在main()结束之前)
  • 实际上,那些triival函数不是没被定义,就是没被调用,程序的行为就如它在C种的表现一样。只有一个小小的例外:
    • 在C种,global被视为一个临时性的定义,因为它没有明确的初始化操作。一个"临时性的定义"可以在程序中发生多次,那些实例会被链接器折叠起来,只留下一个实体,被放在程序data segment种一个特别保留给未初始化的global对象使用的空间。这个空间被称为BSS
    • C++并不支持临时性的定义(这是因为类构造行为的隐含引用之故),因此,global在C++中被视为完全定义(它会阻止第二个或者更多个定义)。C和C++的一个差异在于,BSS数据段在C++中相对的不重要。C++的所有全局对象都被当作初始化过的数据来对象

当编译期遇到如下定义:

/*(2)*/ Point local;
  • 既没有被构造也没有被解构
  • 这个对象不会自动将其成员变量初始化

当编译期遇到如下定义:

/*(6)*/ Point *heap = new Point;
  • 这里会被转换为new运算符的调用:
Point *heap = __new(sizeof(Point));
  • 注意:这里没有默认构造函数施行于new运算符所传回的Point对象上

当编译期遇到如下赋值操作:

/*(7)*/ *heap = local;
  • 理论上,这里的指定操作会触发trivial copy assignment operatir进行拷贝搬运操作
  • 实际上,这个对象是一个POD,所以赋值操作只是像C那样的纯粹位搬移操作

当编译期遇到如下操作:

/*(9)*/delete  heap;
  • 会被转换为对delete运算符的调用:
__delete(heap);
  • 理论上,这样的操作会触发Point的trivial destructor
  • 实际上,destructor要不是没有产生就是没有被调用

当编译期遇到如下操作:

(10) return local;
  • 函数以传值的方式将local传回
  • 理论上会触发trivial copy constructor
  • 实际上return操作只是一个简单的位拷贝操作,因为对象是一个POD

抽象数据类型

以下是Point的第二次声明,在public接口下多了private数据,提供完整的封装性,但没有提供任何虚函数:

  • 没有为Point定义一个拷贝构造函数或者拷贝运算符,因为默认的位语意(default bitwise semantice)已经足够
  • 没有位Point提供一个析构函数,因为程序默认的内存管理也足够了
class Point{
public:
	Point(float x = 0.0, float y = 0.0, float z = 0.0) : _x(x), _y(y), _z(z){
	}
private:
	float _x, _y, _z;
};

这个经过封装的Point类,其大小并没有改变,还是三个连续的float。是的,不论private、public存取层,或者是成员函数的声明,都不会占用额外的对象空间

对于一个global实体:

Point global; // 实施Point::Point(0.0, 0.0, 0.0);
  • 现在有了默认构造函数作用于其上。
  • 由于global被定义在全局范围内,其初始化操作将延迟到程序激活(startup)时才开始


这篇关于C/C++编程:无继承情况下的对象构造的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程