***純虛擬函數***
在設計抽象基類時,需要注意以下幾點:
(1)不要將destructor 聲明為pure virtual function;
如果將destructor聲明為pure virtual function,則設計者一 定得定義它。因為每一個derived class destructor會被編譯器加以擴充,以靜態調用得方式調用其 “每一個virtual base class”以及“上一層base class”的 destructor.
(2)不要將那些函數定義內容並不與類型有關的函數設計為virtual function,因 為其幾乎不會被後繼的derived class改寫。
(3)對於其derived class可能修改某一個data member的函數,不應被聲明為const.
***“無繼承”情況下的物件建構***
先 定義class Point:
class Point {
public:
Point(float x = 0.0, float y = 0.0) : _x(x),_y(y) {}
virtual float z();
protected:
float _x,_y;
};
你可不能小看z()這個virtual function給class Point帶來的巨大變化。virtual function的引入促使每一個class Point擁有一個vtpr,這樣一來,編譯器在constructor中添加了對 vptr進行初始化的代碼,而copy constructor和copy assignment operator也會對vptr進行設定,而不 再是原先簡單的bitwise操作了。
請看以下的代碼:
Point foobar()
{
Point local;
Point *heap = new Point;
*heap = local;
delete heap;
return local;
}
將被內部轉化為:
Point foobar(Point &_result)
{
Point local;
local.Point::Point();
Point *heap = _new (sizeof(Point));
if(heap != 0)
heap->Point::Point();
*heap = local;
_result.Point::Point(local); // copy constructor的應用
local.Point::~Point();
return;
}
從以上代碼的轉化可以看出:一般而言,如果你的設計之中有很多函 數都需要以傳值方式(by value)傳回一個local class object,那麼提供一個copy constructor就比 較合理。
***繼承體系下的物件建構***
假設class Point3d虛擬繼承於class Point,但 由於class Point僅存在一份實體,因而class Point3d的constructor需要注意一個問題。
請看下面的繼承關係圖:
class Point3d : virtual public Point { ... };
class Vertex : virtual public Point { ... };
class Vertex3d : public Point3d, public Vertex { ... };