多态行为

Polymorphism behavior

有人可以帮助解释这种行为差异吗?虚拟函数不应该总是虚拟的吗?产地有关系 virtual-parent/child class.

变体 1:

module test;
   class A;
      virtual function void showMsg(int val);
         $display("This is A");
      endfunction
   endclass
   class B extends A;
       function void showMsg(int val);
         $display("This is B, val = %0d", val);
      endfunction
   endclass
   class C extends B;
      function void showMsg(int val);
         $display("This is C, val=%0d", val+1);
      endfunction
   endclass
   initial begin
      A a;
      B b;
      C c;
      b = new();
      a = b;
     a.showMsg(1);
      c = new();
      b = c;
     b.showMsg(7); 
   end
endmodule

变体 2:

module test;
   class A;
       function void showMsg(int val);
         $display("This is A");
      endfunction
   endclass
   class B extends A;
       virtual function void showMsg(int val);
         $display("This is B, val = %0d", val);
      endfunction
   endclass
   class C extends B;
      function void showMsg(int val);
         $display("This is C, val=%0d", val+1);
      endfunction
   endclass
   initial begin
      A a;
      B b;
      C c;
      b = new();
      a = b;
     a.showMsg(1);
      c = new();
      b = c;
     b.showMsg(7); 
   end
endmodule

变体 1 结果 -

This is B, val = 1 This is C, val=8

Variant2 结果-

This is A This is C, val=8

https://www.edaplayground.com/x/3RMZ

在变体 2 中,A::showMsg 是非虚拟的。调用 a.showMsg 的代码必须表现为非虚拟的,因为它不知道 class 将被扩展。这意味着如果你愿意,A::showMsg 可以有一个与 B::showMsg 完全不同的原型(即不同数量的参数)。但是一旦 B::showMsg 被声明为 virtual,所有派生方法都是 virtual 并且必须具有相同的原型。

如果您声明 virtual A::showMsg,那么它可以在任何派生的 class 中被覆盖。在这种情况下,B::showMsg 是否也是 virtual 并不重要。

class A;
virtual showMsg();
..
class B extends A;
    showMsg();
class C extends B;
    showMsg();

a = c;
a.showMsg() --> calls C::showMsg();
a = b;
a.showMsg() --> calls B::showMsg();

但是,如果 only B::showMsgvirtual,那么 A::showMsg 将不会被覆盖并且任何引用通过基础 class 调用它将从 A 调用该函数。但是,它可以在从 B 派生的任何 class 中重新实现。但是,使用 B 作为基础 class 将调用函数的新实现。

class A;
    showMsg();
..
class B extends A;
    virtual showMsg();
class C extends B;
    showMsg();

a = c; (or a = b;)
a.showMsg() --> calls A::showMsg();
b = c;
b.showMsg() --> calls C:showMsg();

您还错过了一个您想要探索的有趣案例:

 a = c;
 a.showMsg(13);