Polymorphism

Hi All,

Can anyone help me with the output of following code and the reason behind it.

class base;

  virtual task A();
    $display("A called from base class !!");
    B();
    C();
  endtask

  virtual task B();
    $display("B called from base class !!");
  endtask

  task C();
    $display("C called from base class !!");
  endtask
endclass

class child extends base;

  task B();
     $display("B called from extended class !!");
  endtask

  virtual task C();
     $display("C called from extended class !!");
  endtask

  task super_A();
     super.A();
  endtask

endclass

module test;
  initial begin
     base bh;
     child ch;
     ch = new();
     ch.A();
     ch.B();
  end
endmodule


In reply to MarshallX:

It might help to explain what you expected to see displayed versus what actually gets displayed. Then we can comment on any misunderstandings you might have.

In reply to dave_59:

In reply to MarshallX:
It might help to explain what you expected to see displayed versus what actually gets displayed. Then we can comment on any misunderstandings you might have.

Thanks dave for your reply, my question is related?

The output of above code is:

A called from base class !!
Comment: This is understandable).
B called from extended class !!
Comment: Task B is non-virtual in child class, so task call is based on handle type).
C called from base class !!
Comment: Task C is virtual in child class, so task call is based on object type, which is type child, but still task getting called is from base class).
B called from extended class !!
Comment: (This is understandable).

In reply to MarshallX:

In reply to dave_59:
Thanks dave for your reply, my question is related?
The output of above code is:
A called from base class !!
Comment: This is understandable).
B called from extended class !!
Comment: Task B is non-virtual in child class, so task call is based on handle type).
C called from base class !!
Comment: Task C is virtual in child class, so task call is based on object type, which is type child, but still task getting called is from base class).
B called from extended class !!
Comment: (This is understandable).

The output of above code is:

A called from base class !!
B called from extended class !!
C called from base class !!
B called from extended class !!

In reply to MarshallX:

Regarding

“B called from extended class !!
Comment: Task B is non-virtual in child class, so task call is based on handle type).”

This is the expected as according to the LRM section 8.20 Virtual Methods the virtual keyword is optional in the derived classes, In SV once a method is declared as virtual it will be always virtual in all extended/derived classes.

C called from base class !!
Comment: Task C is virtual in child class, so task call is based on object type, which is type child, but still task getting called is from base class).

I Think it is the opposite to the previous case in the base class this method is non-virtual so when doing bh.C() it will call the base class method instead, but in all classes extending from child the behaviour will be the same as in B.

module test;
  initial begin
     base bh;
     child ch;
     ch = new();
     bh = ch;
     ch.A();
     ch.B();
     ch.C();
     bh.C();
  end
endmodule

#Outputs
# KERNEL: A called from base class !!
# KERNEL: B called from extended class !!
# KERNEL: C called from base class !!
# KERNEL: B called from extended class !!
# KERNEL: C called from extended class !!
# KERNEL: C called from base class !!

Probably dave_59 will elaborate more.

HTH,
-R

In reply to rgarcia07:

In reply to MarshallX:
Regarding
This is the expected as according to the LRM section 8.20 Virtual Methods the virtual keyword is optional in the derived classes, In SV once a method is declared as virtual it will be always virtual in all extended/derived classes.
I Think it is the opposite to the previous case in the base class this method is non-virtual so when doing bh.C() it will call the base class method instead, but in all classes extending from child the behaviour will be the same as in B.

module test;
initial begin
base bh;
child ch;
ch = new();
bh = ch;
ch.A();
ch.B();
ch.C();
bh.C();
end
endmodule
#Outputs
# KERNEL: A called from base class !!
# KERNEL: B called from extended class !!
# KERNEL: C called from base class !!
# KERNEL: B called from extended class !!
# KERNEL: C called from extended class !!
# KERNEL: C called from base class !!

Probably dave_59 will elaborate more.
HTH,
-R

Will be thankful to dave_59 for his views and suggestions.

In reply to MarshallX:

The answer is correct.

Another way of thinking about it is to look at the class from the perspective of the class type of the class variable where the handle is stored, not the type of the class object itself. At compile time, it has no way of knowing what object will be stored in the class variable, only that it must be the same type as the class variable or some derivative (I do not like using the term “child” in reference to a derived class). So from the perspective of a base class variable reference bh, A and B are virtual tasks, and C is non-virtual.

In reply to dave_59:

In reply to MarshallX:
The answer is correct.
Another way of thinking about it is to look at the class from the perspective of the class type of the class variable where the handle is stored, not the type of the class object itself. At compile time, it has no way of knowing what object will be stored in the class variable, only that it must be the same type as the class variable or some derivative (I do not like using the term “child” in reference to a derived class). So from the perspective of a base class variable reference bh, A and B are virtual tasks, and C is non-virtual.

Thanks much dave_59 and rgarcia07 for your reply.