MQL4 Virtual Functions
Overview
virtual is used as a function specifier.Example Scenario (Tetris)
CTetrisShape contains a virtual function Draw().CTetrisShape1 and CTetrisShape6 provide their own implementations of the Draw() function.CTetrisField::NewShape(), objects of derived classes are created and assigned to a base class pointer (m_shape). Calling m_shape.Draw() invokes the specific Draw() implementation of the actual object's derived class at runtime.Code Snippets
**Base Class CTetrisShape:**
class CTetrisShape {
protected:
int m_type, m_xpos, m_ypos, m_xsize, m_ysize, m_prev_turn, m_turn, m_right_border;
public:
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[]);
};
**Derived Class CTetrisShape1:**
class CTetrisShape1 : public CTetrisShape {
public:
virtual void Draw() {
int i;
string name;
if(m_turn==0 || m_turn==2) {
// horizontal
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 {
// vertical
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);
}
}
}
};
**Derived Class CTetrisShape6:**
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);
}
}
};
**Object Creation and Call:**
void CTetrisField::NewShape() {
int nshape=rand()%7;
switch(nshape) {
case 0: m_shape=new CTetrisShape1; break;
case 1: m_shape=new CTetrisShape2; break;
case 2: m_shape=new CTetrisShape3; break;
case 3: m_shape=new CTetrisShape4; break;
case 4: m_shape=new CTetrisShape5; break;
case 5: m_shape=new CTetrisShape6; break;
case 6: m_shape=new CTetrisShape7; break;
}
m_shape.Draw(); // Dynamic dispatch occurs here
}
Previous
arrow_back
Overload