Nonstatic Member Function 的语意

C++ 的设计准则之一就是: nonstatic member function 至少必须和一般的 nonmember function 有相同的效率。 这就是说, 如果我们在以下两个函数之间做选择:

float magnitude3d(const Point3d *_this){...}
float Point3d::magnitude3d() const {...}

那么选择 member function 不因该有什么额外负担, 这是因为编译器内部已将 member 函数实体转换为对等的 nonmember 函数实体。
举个例子, 下面是 magnitude() 的一个 nonmember 定义:

float magnitude3d(const Point3d *_this)
{
    return sqrt(_this->_x *this->_x + 
            _this->_y *this->_y +
            _this->_z *this->_z);
}

乍看之下似乎 nonmember function 比较没有效率, 它间接地经由参数取用坐标成员, 而 member function 却是直接取用坐标成员。 但是实际上 member function 被内化为 nonmember 的形式。以下是转换步骤:
1. 改写函数的 signature 以安插一个额外的参数到 member fucntino 中,用以提供一个存取管道, 使 class object 得以调用该函数。该额外函数被称为 this 指针:

//non-const nonstatic member 的增长过程
Point3d
Point3d::magnitude(Point3d *const this)
//如果 memberfunction 是 const, 则变成:
//const nonstatic member 的扩张过程
Point3d
Point3d::magnitude(const Point3d *const this)

2. 将每一个对 nonstatic data member 的存取操作改为经由 this 指针来存取:

{
    return sqrt(_this->_x *this->_x + 
            _this->_y *this->_y +
            _this->_z *this->_z);
}

3. 将 member fucntion 重现写成一个外部函数, 对函数名称进行 mangling 处理, 使它成为程序中独一无二的语汇:

extern magnitude__7Point3dFv(
    register Point3d *const this);

转换好了之后其每个调用操作也需要转换, 于是:

//你看到的
obj.magnitude();
//转换为
mgnitude__7Point3dFv( &obj );

//你看到的
ptr->magnitude();
//变成了:
magnitude__7Point3dFv(ptr);

//你看到的
Point3d
Point3d::normalize() const
{
    register float mag = magnitude();
    Point3d normal;

    normal._x = _x / mag;
    normal._y = _y / mag;
    normal._z = _z / mag;
    return normal;
}
//内部转化为
void normalize__7Point3dFv(register const Point3d *const this,
               Point3d &__result)
{
    register float mag = this->magnitude();
    //default constructor
    __result._x = this->_x / mag;
    __result._y = this->_y / mag;
    __result._z = this->_z / mag;
    return;
}
//另一个比较有效率的方法
Point
Point3d::normalize() const
{
    register float mag = magnitude();
    return Point3d( _x/mag, _y / mag, _z / mag);
}
//这个方法会被转化为
void
normalize__7Point3dFv( register const Point *const this,
            Point3d &__result)
{
    register float mag = this->magnitude();
    __result .Point3d::Point3d(
        _x/mag, _y / mag, _z / mag );
    return;
}


这可以节省 default constrctor 初始化所引起的负担。

posted @ 2014-11-22 16:02  wu_overflow  阅读(854)  评论(0编辑  收藏  举报