400 028 6601

建站动态

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

c++对象模型 成员

class object layout

//64位系统
class A{ };		//sizeof(A)为1
class B : virtual public A{ };	//sizeof(B)为8
class C : virtual public A{ };	//sizeof(C)为8
class D : public B, public C{ };	//sizeof(D)为16

//sizeof(A)为1是因为编译器会安插一个char,使得多个object会有不同的地址

the binding of a data member

extern float x;

class A
{
    public:
    	A(float, float, float);
    	float X() const { return x; };
    
    private:
    	float x, y, z;
}

data member 的存取

​ 现有如下代码:

A a;
//x的存取成本?
a.x = 0.0;
A* ot = &A;
//通过指针的x的存取成本?
pt->x = 0.0

static data members

若由A中的一函数调用static data member,会发生如下转化:

//do为A中的函数
do().i = 0;

//转化求值
(void) do();
A.i = 0;

若取static data member地址,也只会得到指向其类型的指针,并不会指向其class member

&A::i;

//转化
const int*

nonstatic data members

data member的继承

单一继承

​ 现有以下代码:

class Point2d
{
    public:
    	float x() { return _x; }
    	float y() { return _y; }
    	
    	void operation+=( const Point2d& rhs )
        {
            _x += rhs.x();
            _y += rhs.y();
        }
    	...	//constructor
            
    private:
    	float _x, _y;
}

class Point3d
{
    public:
    	float z() { return _z; }
    
    	void operation+=( const Point3d& rhs )
        {
            Point2d::operator+=( rhs );
            _z += rhs.z();
        }
    	...//constructor
    
    private:
    	float _z;
}

多态(单一)继承

​ 现有如下代码:

class Point2d
{
    public:
    	float x() { return _x; }
    	float y() { return _y; }
    	
    	virtual void operation+=( const Point2d& rhs )
        {
            _x += rhs.x();
            _y += rhs.y();
        }
    	
    	virtual float z() { return 0.0; }
    	virtual void z(float) { }
    	...	//constructor
            
    private:
    	float _x, _y;
}

class Point3d
{
    public:
    	float z() { return _z; }
    
    	void operation+=( const Point2d& rhs )
        {
            Point2d::operator+=( rhs );
            _z += rhs.z();
        }
    	...//constructor
    
    private:
    	float _z;
}

//p1和p2可能为Point2d类型,也可能为Point3d类型
void do( Point2d& p1, Point2d& p2 )
{
    p1 += p2;
}

多重继承

​ 现有如下代码:

class Point2d
{
    public:
    ...	//含有virtual函数
        
    protected:
    float _x, _y;
}

class Point3d : public Point2d
{
    ...
    
    protected:
    	float _z;
}

class Vertex
{
    public:
    ... //含有virtual函数
        
    protected:
    	Vertex* next;
}

class Vertex3d : public point3d, public Vertex
{
    ...
    
    protected:
    	float mumble; 
}

Vertex3d v3d;
Vertex* pv;
Point2d* p2d;
Point3d* p3d;

pv = &v3d;
//内部转换 pv = (Vertex*)( ( (char*)&v3d ) + sizeof(Point3d) );

//无需转换
p2d = &v3d;
p3d = &v3d
    
Vertex3d* pv3d;
Vertex* pv;

//若想进行指针的指定操作,还需加个判断
pv = pv3d ? (Vertex*)((char*)pv3d) + sizeof( Point3d );		//pv3d可能为野指针

内存布局:

虚拟继承

​ iostram library:

//对应如下左图
class ios {...};
class istream : public ios {...};
class ostream : public ios {...};
class iostream : public istream, public ostream {...};

//对应如下右图
class ios {...};
class istream : virtual public ios {...};
class ostream : virtual public ios {...};
class iostream : public istream, public ostream {...};

​ 根据如上可知,虚拟继承可以解决存储多个同一base class的问题(ios),那么这是如何实现的呢?

​ 编译期实现策略:

class Point2d
{
    ...
    protected:
    	float _x, _y;
}

class Point3d : virtual public Point2d
{
    ...
    protected:
    	float _z;
}

class Vertex : virtual public Point2d
{
    ...
    protected:
    	Vertex* next;
}

class Vertex3d : public Vertex, public Point3d
{
    ...
    protected:
    	float mumble;
}
void Point3d::operator+=( const Point3d& rhs )
{
    _x += rhs._x;
    _y += rhs._y;
    _z += rhs._z;
}

//进行如下转换

__vbcPoint2d->_x += rhs.__vbcPoint2d->_x;
_z += rhs._z;
----------------------------------分割线-------------------------
    
Point2d* p2d = pv3d;
//进行如下转换
Point2d* p2d = pv3d ? pv3d->__vbcPoint2d : 0;

​ 然而,这种实现模型却存在两个缺点:

​ 解决:

对象成员和指向data member的指针效率


名称栏目:c++对象模型 成员
本文网址:http://mbwzsj.com/article/dsoiehs.html

其他资讯

让你的专属顾问为你服务