028-86922220

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

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

抽象基类

​ 现有如下代码:

创新互联是一家专注于成都网站设计、网站制作与策划设计,东源网站建设哪家好?创新互联做网站,专注于网站建设10余年,网设计领域的专业建站公司;建站业务涵盖:东源等地区。东源做网站价格咨询:18982081108

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
  3. 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;
}

对象构造

不继承

​ 现有如下片段:

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

Point global;

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

​ 现有如下片段:

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 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;
}

继承

T object;

对于以上定义,编译器会扩充每一个constructor。一般而言扩充如下:

​ 实例:

class Point
{
public:
    Point( float x = 0.0, float y = 0.0 );
    Point( const Point& );
    Point& operator=( const Point& );
    
    virtual ~Point();
    virtual float z() { return 0.0; }
    
protected:
    float _x, _y;
};

class Line
{
    Point _begin, _end;
public:
    Line( float = 0.0, float = 0.0, float = 0.0, float = 0.0 );
    Line( const Point&, const Point& ) : _end(end), _begin(begin);
    
    draw();
    ...
};

//扩充
Line* Line::Line( Line* this, const Point&, const Point& )
{
    this->begin.Point::Point( begin );
    this->end.Point::Point( end );
    return this;
}

//合成隐式的Line destructor。若Line派生自Point,合成的将会是virtual
Line a;

vptr初始化

​ 现有如下片段:

//假设每个class都定义了virtual function size(),传回class大小,每个constrcutor中调用size()
Point(x,y);
Point3d(x,y,z);
Vertex(x,y,z);
Vertex3d(x,y,z);
PVertex(x,y,z);

//当我们定义PVertex object,前五个constructor各自调用自己的size()

​ 此时,constructor也需改变:

//改变后的constructor扩张
PVertex* PVertex::PVertex( PVertex* this, bool __most__derived, float x, float y, float z )
{
    //调用virtual base constructor
    if( __most_derived != false ) this->Point::Point(x,y);
    
    //调用上层base class
    this->Vertex3d::Vertex3d(x,y,z);
        
    //初始化vptr
    this->__vptr_PVertex = __vtbl_PVertex;
    this->__vptr_Point__PVertex = __vtbl_Point__PVertex;
    
    //size()
    ...
        
    return this;
}

​ 当然以上方案并不完美:

Point::Point( float x, float y ) : _x(x), _y(y) { }
Point3d::Point3d( float x, float y, float z ) : Point(x,y), _z(z) { }

​ 此时,若声明PVertex,由于对其base class constructor的最新定义,其vptr将不再需要在每个base class constructor中被设定。因此,我们需要把constructor分裂为一个完整的object实例和sunobject实例

对象复制

​ 设计一个class,并以一个class object指定给另一个class object,我们有三种选择:

  1. 什么都不做,实施默认行为
  2. 提供一个explicit copy assignment operator
  3. 显示拒绝把class object指定给另一个class object。也就是将copy assignment operator声明为private,且不提供定义

​ class对于default copy assignment operator,在以下情况,不会表现bitwise copy:

  1. 当class 内含member object,而其class有一个copy assignment operator
  2. 当class的base class有一个copy assignment operator
  3. 当class声明了任何virtual functions。一定别拷贝右边class object的vptr地址,它很有可能是derived class object
  4. 当class继承自virtual base class

对象效能

对象析构

​ destructor被扩展的方式。与constructor相似,但顺序相反:


本文题目:c++对象模型 拷贝、构造、虚构
文章路径:http://www.tsicrk.com/article/dsoiegh.html

其他资讯

让你的专属顾问为你服务

1.6850s