ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c++对象模型 拷贝、构造、虚构

2022-11-08 13:14:47  阅读:321  来源: 互联网

标签:java 函数 学习 系统 语言 平台 方法 安装 QML c++ 数据


class Abstract_base { public: virtual ~Abstract_base() = 0; virtual void interface() const = 0; virtual const char* mumble() const { return _mumble; } protected: char* _mumble; }

​ 以上抽象基类声明有几个问题:

  1. 即使class被声明为抽象基类,其依然需要explicit constructor来初始化protected data member _mumble,否则derived class无法决定_mumble初值
  2. 抽象基类的virtual destructor不要声明为pure。因为每个derived class destructor会被编译器扩张,以静态方式调用每个virtual base class和上一层base class的destructor
 
  1. mumble()不应声明为virtual function,因为其定义的内容和类型无关,derived class并不会改写此函数//合理的声明 class Abstract_base { public: virtual ~Abstract_base(); virtual void interface() = 0; const char* mumble() const { return _mumble; } protected: Abstract_base( char* pc = 0 ); char* _mumble; }
  • 一般而言,class的data member应被初始化,且只在constructor中或在class的其他member function中指定初值。其他操作都会破坏封装性质,让class的维护和修改变得愈加困难
  • 我们可以静态地定义和调用一个pure virtual function,但不能经由虚拟机制
  • c++保证继承体系中每个class object的destructors都能被调用,编译期不可压抑这一操作,且编译器并没有足够知识合成pure virtual destructor函数定义
  • 虚拟基类中,不要把所有的member functions都声明为virtual function,再靠编译器的优化把非必要的虚拟调用去除
  • 虚拟基类中,virtual function不使用const

2|0对象构造

2|1不继承

typedef struct { float x, y, z; }Point; Point global; Point foobar() { Point local; Point* heap = new Point; *heap = local; delete heap; return local; }
  • 对于Point这样的声明,在c++会被贴上Plain OI' Data标签。编译器并不会为其声明default constrcutor、destructor、copy constructor、copy assignment operator

  • 对于 Point global; 这样的定义,在c++中members并没有被定义或调用,行为和c如出一辙。编译器并不会调用constructor和destructor。除非在c中,global被视作临时性定义

    临时性定义:因为没有显示初始化操作,一个临时性定义可以在程序多次发生,但编译器最终会将这些实例链接折叠起来,只留下一个实例,放在data segment中"保留给未初始化的global object使用的"空间 但在c++中并不支持临时性定义,对于此例,会阻止后续的定义
  • c++中所有全局对象都被以初始化过的数据对待

  • 对于 Point* heap = new Point;编译器并不会调用default constructor,只是 Point* heap = __new( sizeof(Point) )。delete亦是如此

  • 对于*heap = local;编译器并不会调用copy assignment operator做拷贝,但只是像c那样做简单的bitwise

  • return操作也是,只是简单的bitwise,并没有调用copy constructor

class Point { public: Point( float x = 0.0, float y = 0.0, float z = 0.0 ) : _x(x), _y(y), _z(z) { } //没有copy constructor,copy operator,destructor private: float _x, _y, _z; } void do() { Point local1 = {1.0, 1.0, 1.0}; }
  • 对于将class中成员设定常量值,使用explicit initialization list更有效率。因为当函数的活动记录(activation record)被放进堆栈,initialization list的常量即可放入local1内存中

    活动记录过程的调用是过程的一次活动,当过程语句(及其调用)结束后,活动生命周期结束。变量的生命周期为其从被定义后有效存在的时间
  • 但explicit initialization list也有不足:

    • class member需要为public
    • 只能指定常量,因为其常量在编译器即可求值
    • 编译器并没有自动施行它,初始化很可能失败
  • 若调用之前的例子,放在现在编译器也不会调用destructor,因为并没有显示地提供destructor
    delete heap;

class Point { public: Point( float x = 0.0, float y = 0.0, float z = 0.0 ) : _x(x), _y(y), _z(z) { } virtual float z(); //没有copy constructor,copy operator,destructor private: float _x, _y; }
  • 导入了virtual functions会引发编译器对class Point的膨胀:

    • 定义的constructor附加一些代码,以便将vptr初始化。这些代码附加在任何base class constructors调用后,user code之前
    • 合成一个copy constructor 和 一个assignment operator,且不再是有用的(trivial),但implicit desctructor仍为有用的
  • 这种情况下,编译器在优化状态下可能会把object的连续内容拷贝到另一个object上,且不是memberwise。因此,编译器会尽量延迟nontrivial members的合成操作,直到遇到合适场合

标签:java,函数,学习,系统,语言,平台,方法,安装,QML,c++,数据
来源:

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有