深度探索 C++ 对象模型 04:成员函数

xiaoxiao2025-11-08  6

C++ 支持三种 member function:static、nonstatic 和 virtual

Member Function 的调用方式

nonstatic member function

C++ 保证 nonstatic member function 至少和普通 non-member function 有相同的效率,member function 会被内部转化为 non-member function 的形式 double magnitude(const Point3d* p3d) { return sqrt(p3d->x * p3d->x + p3d->y * p3d->y + p3d->z * p3d->z); } double Point3d::magnitude const () { return sqrt(x*x + y*y + z*z); } Point3d point, *p3d; point.magnitude(); p3d->magnitude(); // 程序转化,包括名字编码 double magnitude__7Point3dFv(const Point3d *const this) { return sqrt(this->x * this->x + this->y * this->y + this->z * this->z); } magnitude_7Point3dFv(&point); magnitude_7Point3dFv(p3d); Point3d Point3d::normalize() const { register double 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 double mag = this->magnitude(); __result.Point3d::Point3d(); __result.x = this->x / mag; __result.y = this->y / mag; __result.z = this->z / mag; return; } Point3d Point3d::normalize() const { register double mag = magnitude(); return Point3d(x/mag, y/mag, z/mag); } // 程序转化 void normalize_7Point3dFv(register const Point3d *const this, Point3d& __result) { register double mag = this->magnitude(); __result.Point3d::Point3d(this->x/mag, this->y/mag, this->z/mag); return; }

virtual member function

// 若 normalize() 是 virtual member function,那么 p3d->normalize(); point.normalize(); // 会转化为 (*p3d->vptr[1])(p3d); (point.vptr[1])(&point);

static member function

// 若 normalize() 是 static member function,那么 p3d->normalize(); point.normalize(); // 会转化为 normalize_7Point3SFv(); normalize_7Point3SFv(); static member function 的特性 没有 this 指针不能直接存取 class 的 nonstatic member不能被声明为 const、volatile 或 virtual不需要经由 class object 调用

Virtual Member Function

C++ 中,多态表示以一个 public base class 的指针或引用寻址出一个 derived class object经由 public base class pointer or reference,可以在程序的任何地方采用一组 public derived class Point* pp; pp = new Point2d; pp = new Point3d; 一个 class 只有一个 virtual table,每个 table 包含所有的 active virtual function 实体的地址,包括 class 所定义的函数实体,会改写可能存在的 base class virtual function 实体继承自 base class 的函数实体,此时 class 没有改写 base class 的 virtual functionpure_virtual_called() 每个 virtual function 配有一个固定的索引值

单一继承

class Point { public: Point() : _x(0) {} Point(double x) : _x(x) {} virtual ~Point(); virtual Point& mult(double) = 0; // pure virtual function double x() const { return _x; } virtual double y() { return 0.0; } virtual double z() { return 0.0; } protected: Point(double x = 0.0); double _x; }; // virtual ~Point() 在 vtbl 中的索引为 1 // mult() 为 pure virtual function,没有函数定义,因此 pure_virtual_called() 的索引为 2 // y() 和 z() 的索引分别为 3 和 4 // vtbl 中索引为 0 的位置存放 Point 的 type_info class Point2d : public Point { public: Point2d() : Point(), _y(0) {} Point2d(double x = 0.0, double y = 0.0) : Point(x), _y(y) {} ~Point2d(); Point2d& mult(double); // rewrite base class virtual function double y() { return _y; } // rewrite base class virtual function protected: double _y; }; class Point3d : public Point2d { public: Point3d() : Point2d(), _z(0) {} Point3d(double x = 0.0, double y = 0.0, double z = 0.0) : Point2d(x, y), _z(z) {} Point3d& mult(double); // rewrite base class virtual function double z() { return _z; } // rewrite base class virtual function protected: double _z; }; // 当出现以下调用时 ptr->z(); // 1. 编译时期并不知道 ptr 所指对象的真正类型,但经由 ptr 可以访问到该对象的 vtbl // 2. 每一个 z() 的地址都放在 vtbl[4] 中 // 因此以上调用可转换为 (*ptr->vptr[4])(ptr); // 到运行期便可根据 ptr 所指的对象调用 z() 的正确实体

多重继承

class Base1 { public: Base1() {} virtual ~Base1(); virtual void speak(); virtual Base1* clone() const; protected: double _datab1; }; class Base2 { public: Base2() {} virtual ~Base1(); virtual void mumble(); virtual Base2* clone() const; protected: double _datab2; }; class Derived : public Base1, public Base2 { public: Derived() {} virtual ~Derived(); virtual Derived* clone() const; private: double _datad; };

在多重继承下,一个 derived class 内含的 vtbl 与它的直接父类个数相同针对每一个 vtbl,derived class 对象中都有一个 vptr 与之对应 当把 Derived 对象地址赋给 Base1 指针或 Derived 指针时,访问 vtbl_Derived当把 Derived 对象地址赋给 Base2 指针时,访问 vtbl_Base2_Derived

虚拟继承

不要在 virtual base class 中声明 nonstatic data member!

转载请注明原文地址: https://www.6miu.com/read-5039257.html

最新回复(0)