Can derived class object call base class (virtual/non-virtual) function?

Hello,

I need a clarification regarding Inheritance and Polymorphism.


class A;
  function void display();
    ...
  endfunction : display
endclass : A

class B extends A;
  function void display();
    ...
  endfunction : B
endclass : B

class C;
  virtual function void display();
    ...
  endfunction : display
endclass : C

class D extends C;
  virtual function void display();
    ...
  endfunction : display
endfunction : D

Class B extends Class A and both have non-virtual display function.
Class D extends Class C and both have virtual display function.


A A0 = new();
B B0 = new();

A0.display(); //call A::display() using A object.
B0.display(); //call B::display() using B object.
A0 = B0; or $cast(A0, B0); //VALID as per SV.
A0.display(); //still will call A::display(). Non-virtual display function in class A.
B0 = A0; or $cast(B0, A0); //ERROR as per SV.

C C0 = new();
D D0 = new();

C0.display(); //call C::display() using C object.
D0.display(); //call D::display() using D object.
C0 = D0; or $cast(C0, D0); //VALID as per SV.
C0.display(); //call D::display() using C object. Virtual display function in class C.
D0 = C0; or $cast(D0, C0); //ERROR as per SV.

Q 1 → In above code snippets (unverified), irrespective of the type of display function (virtual or non-virtual), the base class display function could not be invoked using a derived class object. Is there any other way to achieve the above discussed scenario? Please explain.

Q 2 → Does the derived class display function necessarily should be virtual if the base class display function is declared as virtual?

Q 3 → Can derived class display function be declared as virtual when the base class display function is non-virtual?

Thanks,
-Vignesh

Q 1: Since you’ve overwritten the display() function in the extended class, you will need to call super from within the derived class if you want to call the base class function. I included an example. You can include super.display() also in the display function of your extended class. (not a separate function as I coded)

Q 2: Functionally, no. However, I include it to show intent. From LRM: A virtual method may override a non-virtual method, but once a method has been identified as virtual, it
shall remain virtual in any subclass that overrides it. In that case, the virtual keyword may be used in later declarations, but is not required.

Q 3: Yes. The above quote applies here as well. Once you go virtual, you never go back, as they say.

I coded it up in EDA playground so you could play with it:

ps you made a statement unintentionally near the end that was incorrect… I fleshed it out in my example, but
D0 = C0; or $cast(D0, C0); //ERROR as per SV.

The $cast statement in bold is not an error; it is actually just a “downcast”, a common and useful feature if your extended class has additional data members, and you have a base handle but need access to the extended class members.

In reply to bmorris:

Thanks Morris.
I have one point to add.

The assignment from child_handle to parent_handle is always allowed, but an assignment the reverse direction can only be checked at runtime using $cast.

In the simulation you had pointed me to, I notice that the last D0.display() after casting ($cast(D0,C0)) prints “D!” in output console. $cast(D0, C0) doesn’t throw errors only because, we assign C0 = D0 before casting. Had we not done C0 = D0, this would have been an error.

Error-[DCF] Dynamic cast failed
testbench.sv, 57
Casting of source class type ‘C’ to destination class type ‘D’ failed due to
type mismatch.
Please ensure matching types for dynamic cast

In reply to Vignesh Raghavan:

You are correct; the parent handle must be first be pointing to a child object in order for the dynamic cast to succeed. This is why it returns a pass/fail.
The D0=C0 will fail always.
Thanks for the question; I learned a lot. ^_^