virtualキーワードは関数指定子です。
これは、実行時に基本クラスと派生クラスの関数から適切な関数を動的選択するメカニズムです。
構造体は仮想関数を持つ事は出来ません。
関数メンバの宣言を変更する為だけに使用する事が出来ます。
仮想関数は通常の関数のように実行可能な本体を持っている必要があります。
呼び出された時、そのセマンティックは他の関数と同じです。
仮想関数は派生クラスでオーバーライドする事が出来ます。
仮想関数の為にどの関数定義が選択されるかは動的(実行時)に行われます。
基本クラスに仮想関数が含まれているのが典型的なケースで、派生クラスはこの関数の独自のバージョンを持っています。
基本クラスへのポインタは、基本クラスオブジェクトまたは派生クラスオブジェクトのいずれかを示す事が出来きます。
呼び出すメンバ関数の選択は実行時に行われ、ポインタの型では無くオブジェクトの型に依存します。
派生型のメンバが無い場合は、基本クラスの仮想関数はデフォルトで使用されます。
デストラクタはvirtualキーワード宣言の有無に関係無く、常に仮想です。
例:
class CTetrisShape {
protected :
int m_type;
int m_xpos;
int m_ypos;
int m_xsize;
int m_ysize;
int m_prev_turn;
int m_turn;
int m_right_border;
public :
void CTetrisShape();
void SetRightBorder( int border) { m_right_border = border; }
void SetYPos( int ypos) { m_ypos = ypos; }
void SetXPos( int xpos) { m_xpos = xpos; }
int GetYPos() { return (m_ypos); }
int GetXPos() { return (m_xpos); }
int GetYSize() { return (m_ysize); }
int GetXSize() { return (m_xsize); }
int GetType() { return (m_type); }
void Left() { m_xpos -= SHAPE_SIZE; }
void Right() { m_xpos += SHAPE_SIZE; }
void Rotate() { m_prev_turn = m_turn; if ( ++m_turn > 3 ) m_turn=0; }
virtual void Draw() { return ; }
virtual bool CheckDown( int & pad_array[]);
virtual bool CheckLeft( int & side_row[]);
virtual bool CheckRight( int & side_row[]);
};
クリップボードにコピー
それぞれの派生クラスでは、この関数は下位クラスの特徴に応じて実装されます。
例えば最初の形状CTetrisShape1はDraw()関数が実装されます。
class CTetrisShape1 : public CTetrisShape {
public :
virtual void Draw() {
int i;
string name;
if ( m_turn == 0 || m_turn == 2 ) {
for ( i=0; i < 4; i++) {
name = SHAPE_NAME + (string )i;
ObjectSetInteger (0,name,OBJPROP_XDISTANCE , m_xpos + i * SHAPE_SIZE);
ObjectSetInteger (0,name,OBJPROP_YDISTANCE , m_ypos );
}
} else {
for ( i=0; i < 4; i++ )
{
name = SHAPE_NAME + (string )i;
ObjectSetInteger (0,name,OBJPROP_XDISTANCE , m_xpos );
ObjectSetInteger (0,name,OBJPROP_YDISTANCE , m_ypos + i * SHAPE_SIZE);
}
}
}
};
クリップボードにコピー
正方形形状はCTetrisShape6クラスで記述され独自のDraw()メソッドを実装します。
class CTetrisShape6 : public CTetrisShape {
public :
virtual void Draw() {
int i;
string name;
for ( i=0; i < 2; i++) {
name = SHAPE_NAME + (string )i;
ObjectSetInteger (0,name,OBJPROP_XDISTANCE , m_xpos + i * SHAPE_SIZE);
ObjectSetInteger (0,name,OBJPROP_YDISTANCE , m_ypos );
}
for ( i=2; i < 4; i++) {
name = SHAPE_NAME + (string )i;
ObjectSetInteger (0,name,OBJPROP_XDISTANCE , m_xpos + (i-2) * SHAPE_SIZE);
ObjectSetInteger (0,name,OBJPROP_YDISTANCE , m_ypos + SHAPE_SIZE);
}
}
};
クリップボードにコピー
クラスに応じて作成されたオブジェクトが属します、それはこの仮想関数か派生クラスの仮想関数を呼び出します。