In Inheritance, we saw that methods invoked by a base class handle which points to a child class instance would eventually end up executing the base class method instead of the one in child class. If that function in the base class was declared as virtual, only then the child class method will be executed.


	bc = sc;            // Base class handle is pointed to a sub class
	
	bc.display ();      // This calls the display() in base class and 
	                    // not the sub class as we might think

We'll use the same classes from previous session and do a comparison with and without virtual function.

Without virtual keyword


// Without declaring display() as virtual
class Packet;
   int addr;

   function new (int addr);
      this.addr = addr;
   endfunction

   // This is a normal function definition which 
   // starts with the keyword "function"
   function void display ();
		$display ("[Base] addr=0x%0h", addr);
   endfunction
endclass

module tb;
   Packet bc;
   ExtPacket sc;

	initial begin
        sc = new (32'hfeed_feed, 32'h1234_5678);	

        bc = sc; 
		bc.display ();
	end
endmodule
 Simulation Log
ncsim> run
[Base] addr=0xfeedfeed
ncsim: *W,RNQUIE: Simulation is complete.

Note that the base class display() function gets executed.


With virtual keyword


class Packet;
   int addr;

   function new (int addr);
      this.addr = addr;
   endfunction

   // Here the function is declared as "virtual"
   // so that a different definition can be given
   // in any child class
   virtual function void display ();
		$display ("[Base] addr=0x%0h", addr);
	endfunction
endclass

module tb;
   Packet bc;
   ExtPacket sc;

	initial begin
        sc = new (32'hfeed_feed, 32'h1234_5678);	

        bc = sc; 
		bc.display ();
	end
endmodule
 Simulation Log
ncsim> run
[Child] addr=0xfeedfeed data=0x12345678
ncsim: *W,RNQUIE: Simulation is complete.

Note that the child class display() function gets executed when the base class function is made virtual.

The key takeaway is that you should always declare your base class methods as virtual so that already existing base class handles will now refer the function override in the child class.