Cpp_类和对象

围绕具体问题对属性和行为进行有意识的选择,使复杂的具体问题得到简化——面向对象的程序设计

类的定义与实例化

1.类的一般形式

class/struct 类名 : 继承方式 基类, … {
访问控制限定符:
类名 (形参表) : 成员变量 (初值), … { // 构造函数
函数体;
}
~类名 (void) { // 析构函数
函数体;
}
返回类型 函数名 (形参表) 常属性 异常说明 { // 成员函数
函数体;
}
数据类型 变量名; // 成员变量
};

2.访问控制限定符
  • 公有成员——public:谁都可以访问。

  • 私有成员——private:只有该类自己的成员函数可以访问。

  • 保护成员——protected:只有该类及其子类的成员函数可以访问。

3.成员函数

C++支持三种类型的成员函数,static,nonstatic和virtual,每一种成员函数被调用的方式都不同。
3.1nonstatic成员函数
原始的”C-withClass”只支持nonstatic成员函数
C++的设计准则是nonstatic member function至少需要和非成员函数具有相同的执行效率。
编译器实际上将成员函数内化为非成员函数

在这里举一个例子
假设有类的成员函数

float Point3D::magnitude3d()const{
    return sqrt(_x*_x + _y*_y + _z*_z);
}

转化为非成员函数的过程大概需要经过以下几个步骤

1)首先改写函数原型,将一个额外的参数安插到成员函数中,用来提供一个存取的管道,该额外的参数被称为this指针

float Point3D::magnitude3d(Point *const this)const{
return sqrt(_x*_x + _y*_y + _z*_z);
}

2)在函数体内对成员数据的存取通过this指针来完成

float Point3D::magnitude3d(Point *const this)const{
    return sqrt(this->_x*this->_x + this->_y*this->_y + this->_z*this->_z);
}

3) 最后讲成员函数重写为外部的一个函数,对其函数名进行”mangling”处理,使其称为独一无二的标识。

extern magnitude_7Ponint3dFv(register Point3d *const this);
Tips:mangling处理规则:一般成员名前面加上类名会形成独一无二的名称,不过再加上参数列表就会确保名称这时会是独一无二的了

这时,成员函数已经转化好了,而我们的代码中通过对象对其进行的每次调用,这时也需要有形式上的改变。

obj.magnitude();    ⇒   magnitude_7Ponint3dFv(&obj);

ptr->magnitude();   ⇒   magnitude_7Ponint3dFv(ptr);
void normalize_7Ponint3dFv(register Point3d *const this,Point3d &_result){
    register float mag = this->magnitude();
    _result.Point3d::Point3d(this->_x/mag,this->_y/mag,this->_y/mag) ;  //假设Point3d的copy constructor已经声明好了  
    return;
}

Virtual Member Function

若normalize函数是一个虚函数,它会经历如下的内部转换

ptr->normalize();   ⇒  (*ptr->vptr[1])(ptr);

其中vptr是由编译器生成的虚表指针,实际上vptr的名字也会被mangled

而此时如果magnitude函数也是一个虚函数,则它在normalize函数中的调用操作将会被转化为如下的形式

register float mag = magnitude();  ⇒  register float mag = (*this->vptr[2])(this);

这里要说明一下,由于magnitude在normalize中调用,而后者已经已经由虚拟机制resloved(具体的对象已经确定,不必再通过虚指针来进行),所以明确地调用Ponint3d实体会比较由效率

register float mag = Point3d::magnitude();

magnitude函数声明为inline函数会更有效率,使用类的域解析符::调用一个virtual函数,其resolved方式会和nonstatic 成员函数一样。

经由类对象调用的虚函数(注意这里说的并不是基类对象的指针)这种操作应该总是被编译器对待一般的nonstatic 成员函数一样地resolved
像是这样:

Point3d obj;
obj.normalize(); =>   normalize_7Point3dFv(&obj);

Static Member Function

若normalize函数是一个静态成员函数,其调用操作会转化为对一个nonmember function的调用

在引入静态成员函数之前,C++要求语言要求所有的成员函数都要经过对象来调用,但是如果这个成员函数中没有对成员进行存取,也就不需要this指针,这样也就没有必要通过类的对象来调用成员函数。

所以当时出现了这样一种写法:

((Point3d *)0)->object_count(); 
//函数object_count()函数只是简单地传回一个static data member

上面的调用接着会被转化为object_count((Point3d *)0)
把0强制转化为类的指针,因而也就会提供出了一个this指针,之所以把0强转,是因为这个this指针根本用不到!!!

当之后推出了static member function之后,它的最主要的特性就是没有this指针,所以也就不能直接存取类中的非静态成员,也不能被声明为const,volatile或者virtual,不需要通过类对象来调用(并不是说不能!)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值