《深度探索c++对象模型》第四章:(成员)函数

  假设现有一个3d点坐标,将其归一化:

Point3d Point3d::normalize() const{
   
	//register表示该变量常用,请求编译器将变量存储在寄存器里,加快存取速度,但是编译器不一定会放寄存器里
	//注意由于该变量不一定放在内存,所以不能用&取地址
	register float mag=magnitude();
	Point3d normal;
	normal._x = _x/mag;
	normal._y = _y/mag;
	normal._z = _z/mag;
	return normal;
}

float Point3d::magnitude() const{
   
	return sqrt(_x*_x+_y*_y+_z*_z);
}

Point3d obj;
Point3d *ptr=&obj;
obj.normalize();
ptr->normalize();

  c++支持三种成员函数:static,non-static,virtual,每一种类型的函数被调用的方式不一样,下面会详细叙述。虽然我们不能确定normalize()和magnitude()是不是virtual函数,但是可以确定它们不是static函数:
  (1)static函数无法直接存取non-static数据。因为static函数是属于整个类的,通过类名::函数名来调用,而non-static数据是属于具体的对象的。
  (2)static函数不能声明为const函数(这里指的是const放在函数末尾)

4.1各种成员函数的调用方式

非静态成员函数

  C++设计准则之一:非静态函数至少要和一般的函数(非成员函数)由相同的效率:

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

  根据上面的准则,成员函数不应该带来任何负担,这是因为编译器内部已经将成员函数实体转换成非成员函数实体。例如:

float magnitude3d(const Point3d *_this){
   
	return sqrt(_this->_x * _this->_x + _this->y * _this->y + _this->z * _this->z);
}

  看起来好像非成员函数效率比成员函数低,因为非成员函数间接地通过参数(*_this)取用坐标成员,而成员函数直接取用坐标成员。然而实际上成员函数会被内化成非成员函数的形式,转化步骤为:
  1、改变函数原型,安插一个额外的参数(this指针)到成员函数中,使得对象可以调用这个函数,也使得这个函数可以存取对象的成员。

//原型:
float Point3d::magnitude() const;
//第一步 改变函数原型:
float Point3d::magnitude(Point3d *const this) const;
//第一步 改变函数原型(如果成员函数是const):
float Point3d::magnitude(const Point3d *const this) const;
//这里由于函数原型末尾有const,表明这是一个只读(read-only)函数
//不能在这个函数里修改成员变量(所以*this指针前要加个const)和调用非const成员函数

  2、用this指针来存取非静态数据成员

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

  3、将成员函数重写成一个外部函数,对函数名称进行"mangling"处理,使它在程序中拥有独一无二的名称。

extern magnitude3d_7Point3dFv(register Point3d *const this);

  经过上面三个步骤,函数已经转换好了,而其每一个调用操作也必须转换:

//原先调用操作
obj.magnitude();
ptr->magnitude();
//转换成
magnitude_7Point3dFv(&obj);
magnitude_7Point3dFv(ptr);

  magnitude函数已经转换完成,再看看normalize函数的转化,假设Point3d声明中有一个拷贝构造函数,而且name returned value(NVR)优化也已经施行(关于NVR优化可以看回2.3节编译层面):

//"name returned value"函数的内部转化,c++伪码
//无返回值,加一个引用参数当做返回值
void normalize_7Point3dFv(register const Point3d *const this, Point3d &_result){
   
	register float mag=this->magnitude();
	_result.Point3d::Point3d();	//构造_result
	
	_result._x=this->_x/mag;
	_result._y=this->_y/mag;
	_result._z=this->_z/mag;
	
	return;
}

  normalize的另一个比较有效率的做法是直接构建"normal"值,像这样:

Point3d Point3d::normalize() const{
   
	register float mag=magnitude();
	return Point3d(_x/mag,_y/mag,_z/mag);
}

  它会被转化为一下的代码,再次假设Point3d声明了拷贝构造函数,且NVR优化已经施行:

//上述代码转化为(c++伪码):
void normalize_7Point3dFv(register const Point3d *const this, Point3d &_result){
   
	register float mag= this->magnitude();
	//_result用来取代返回值
	_result.Point3d::Point3d(this->_x/mag
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值