1、非靜態成員函數轉化為非成員函數
c++ 設計準則之一就是:非靜態成員函數至少和非成員函數有相同的效率。
也就是說下面兩個函數具有相同的效率:
float magnitude(const Point3d * this){...};
float Point3d::magnitude(){...};
以
float Point3d::magnitude()
{
return sqrt(x * x + y * y + z * z);
}
為例。
magnitude函數被轉化為非成員函數的步驟如下:
1.1 改寫函數原型,在第一個參數的位置安插this指針。
float Point3d::magnitude( Point3d * const this);
如果成員函數是const 則變成
float Point3d::magnitude(const Point3d * const this);
1.2 將對非靜態成員的存取改為經this指針存取:
return sqrt(this->x * this->x + this->y * this->y + this->z * this->z);
1.3 將成員函數重寫成一個外部函數,并處理函數名:
magnitude() -> *magnitude_7Point3dFv(Point3d const this)
obj.magnitude(); -> magnitude_7Point3dFv(&bj);
ptr->magnitude(); -> magnitude_7Point3dFv(ptr);
2、 名稱的特殊處理(Name Mangling)
2.1 數據成員名稱的處理
一般情況下,會在成員名稱后加上類名。
例:
class Bar
{
public:int ival;
};calss Foo : public Bar
{
public:int ival;
};
Foo會被處理成下面這樣
calss Foo
{
public:int ival_3Bar; //父類的成員int ival_3Foo; //Foo的成員
};
2.2 成員函數名稱的處理
因為c++支持函數重載,所以在處理成員函數名稱的時候加上了參數列表。
下面是Point類的定義:
class Point
{
public:
void x();
float x(float)
};
下面是處理后的Point類
class Point
{
public:
void x_5PoitFv();
float x_5PoitFf(float)
};
3、 虛擬成員函數
加入我們有一個Point類如下:
class Point
{
public:virtual void normalize();
}
那么下面的調用
ptr->normalize();
會被轉化為
(*ptr->vptr[1])->(ptr);
- vptr表示指向虛函數表的指針。
- 1是normalize在虛表中的索引值
- 第二個 ptr 表示this指針
4、靜態成員函數
如果上面Point中normalize函數是靜態函數,則別轉換為一般的非成員函數:
obj.normalize() -> normalize_5PointSFv()
ptr->normalize() -> normalize_5PointSFv()
4.1、靜態成員函數的特性
- 它不能夠直接存儲非靜態成員。
- 他不能聲明為const、virtual 或volatile。
- 他不需要經由類對象調用
5、指向成員函數的指針
如有Point類如下:
class Point
{
public:
float get_x();
void set_x(float)
};
下面定義指向get_x和set_x函數的指針:
float (Point::*f_get_x)() = &Point::get_x;void (Point::*f_set_x)(float) = &Point::set_x;