Virtual Functions
Continuing with the example of Enemy class in the Inheritance and Polymorphism post, consider that we want every enemy to attack using the attack() function.
To be able to call the corresponding attac() function for each of the derived classes using Enemy pointers, the base class function needs to be declared as virtual. Defining a virtual function in the base class, with a corresponding version in a derived class, allows polymorphism to use Enemy pointers to call the derived classes' functions.
Every derived class will override the attack() function and have a separate implementation:
class Enemy {
public:
virtual void attack() {
}
};
class Ninja: public Enemy {
public:
void attack() {
cout << "Ninja!"<<endl;
}
};
class Monster: public Enemy {
public:
void attack() {
cout << "Monster!"<<endl;
}
};
Now, the Enemy pointers can be used to call the attack() function.
int main() {
Ninja n;
Monster m;
Enemy *e1 = &n;
Enemy *e2 = &m;
e1->attack();
e2->attack();
}
/* Output:
Ninja!
Monster!
*/
The game example serves to demonstrate the concept of polymorphism; we are using Enemy pointers to call the same attack() function, and generating different results.
e1->attack();
e2->attack();
If a function in the base class is virtual, the function's implementation in the derived class is called according to the actual type of the object referred to, regardless of the declared type of the pointer.
Virtual functions can also have their implementation in the base class:
class Enemy {
public:
virtual void attack() {
cout << "Enemy!"<<endl;
}
};
class Ninja: public Enemy {
public:
void attack() {
cout << "Ninja!"<<endl;
}
};
class Monster: public Enemy {
public:
void attack() {
cout << "Monster!"<<endl;
}
};
Now, when an Enemy pointer is created, and the attack() function is called, the compiler will call the function, which corresponds to the object's type, to which the pointer points:
int main() {
Ninja n;
Monster m;
Enemy e;
Enemy *e1 = &n;
Enemy *e2 = &m;
Enemy *e3 = &e;
e1->attack(); // Outputs "Ninja!"
e2->attack(); // Outputs "Monster!"
e3->attack(); // Outputs "Enemy!"
}
The pure virtual function in the Enemy class needs to be overridden in it's derived classes.
class Enemy {
public:
virtual void attack() = 0;
};
class Ninja: public Enemy {
public:
void attack() {
cout << "Ninja!"<<endl;
}
};
class Monster: public Enemy {
public:
void attack() {
cout << "Monster!"<<endl;
}
};
Objects of the base class with a pure virtual function cannot be created. Running the following code will return an error:
Ninja n;
Monster m;
Enemy *e1 = &n;
Enemy *e2 = &m;
e1->attack();
e2->attack();
Every derived class will override the attack() function and have a separate implementation:
class Enemy {
public:
virtual void attack() {
}
};
class Ninja: public Enemy {
public:
void attack() {
cout << "Ninja!"<<endl;
}
};
class Monster: public Enemy {
public:
void attack() {
cout << "Monster!"<<endl;
}
};
A virtual function is a base class function that is declared using the keyword virtual.
Now, the Enemy pointers can be used to call the attack() function.
int main() {
Ninja n;
Monster m;
Enemy *e1 = &n;
Enemy *e2 = &m;
e1->attack();
e2->attack();
}
/* Output:
Ninja!
Monster!
*/
The game example serves to demonstrate the concept of polymorphism; we are using Enemy pointers to call the same attack() function, and generating different results.
e1->attack();
e2->attack();
If a function in the base class is virtual, the function's implementation in the derived class is called according to the actual type of the object referred to, regardless of the declared type of the pointer.
A class that declares or inherits a virtual function is called a polymorphic class.
Virtual functions can also have their implementation in the base class:
class Enemy {
public:
virtual void attack() {
cout << "Enemy!"<<endl;
}
};
class Ninja: public Enemy {
public:
void attack() {
cout << "Ninja!"<<endl;
}
};
class Monster: public Enemy {
public:
void attack() {
cout << "Monster!"<<endl;
}
};
Now, when an Enemy pointer is created, and the attack() function is called, the compiler will call the function, which corresponds to the object's type, to which the pointer points:
int main() {
Ninja n;
Monster m;
Enemy e;
Enemy *e1 = &n;
Enemy *e2 = &m;
Enemy *e3 = &e;
e1->attack(); // Outputs "Ninja!"
e2->attack(); // Outputs "Monster!"
e3->attack(); // Outputs "Enemy!"
}
Pure Virtual Functions :
In some situations, a virtual function
in a base class would need to be included, so that it may be redefined in a derived class to suit
the objects of that class, but that there is no meaningful definition that would be given for the function in the base class.
The virtual member functions without definition are known as pure virtual functions. They basically specify that the derived classes define that function on their own.
The syntax is to replace their definition by =0 (an equal sign and a zero):
The virtual member functions without definition are known as pure virtual functions. They basically specify that the derived classes define that function on their own.
The syntax is to replace their definition by =0 (an equal sign and a zero):
class Enemy {
public:
virtual void attack() = 0;
};
public:
virtual void attack() = 0;
};
The =0 tells the compiler that the function has no body.
A pure virtual function basically defines, that the derived classes will have that function defined on their own. Every derived class inheriting from a class with a pure virtual function must override that function.
If the pure virtual function is not overridden in the derived class, the code fails to compile and results in an error when you try to instantiate an object of the derived class.
The pure virtual function in the Enemy class needs to be overridden in it's derived classes.
class Enemy {
public:
virtual void attack() = 0;
};
class Ninja: public Enemy {
public:
void attack() {
cout << "Ninja!"<<endl;
}
};
class Monster: public Enemy {
public:
void attack() {
cout << "Monster!"<<endl;
}
};
Abstract Classes :
Objects of the base class with a pure virtual function cannot be created. Running the following code will return an error:
Enemy e; //Returns error
These classes are called abstract. They are classes that can only be used as base classes, and thus are allowed to have pure virtual functions. It might be thought that an abstract base class is useless, but it isn't. It
can be used to create pointers and take advantage of all its polymorphic
abilities.
For example, it could be written as :
Ninja n;
Monster m;
Enemy *e1 = &n;
Enemy *e2 = &m;
e1->attack();
e2->attack();
Objects of different but related types are referred to using a unique type of pointer (Enemy*), and the proper member function is called every time, just because they are virtual.
Comments
Post a Comment