Полиморфизм поведения - PullRequest
       24

Полиморфизм поведения

0 голосов
/ 29 декабря 2018

Может ли кто-нибудь помочь объяснить эту разницу в поведении?Разве виртуальные функции не должны быть всегда виртуальными?Имеет ли значение, где создается виртуальный родительский / дочерний класс.

Вариант 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 результаты-

Это B, val = 1 Это C, val = 8

Результаты Variant2-

Это A Это C, val =8

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

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Если вы объявите virtual A::showMsg, его можно переопределить в любом производном классе.В этом случае не имеет значения, является ли B::showMsg также виртуальным или нет.

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::showMsg равно virtual , A::showMsg не будет переопределено, и любая ссылка на него через базовый класс будет вызыватьэта функция с A.Однако он может быть повторно реализован в любом классе, производном от B.Однако использование B в качестве базового класса вызовет новую реализацию функции.

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);
0 голосов
/ 30 декабря 2018

В варианте 2 A::showMsg не является виртуальным.Код, вызывающий a.showMsg, должен вести себя как не виртуальный, поскольку он не знает, что класс будет расширен.Это означает, что A::showMsg может иметь совершенно другой прототип, чем B::showMsg, если вы хотите (т.е. другое количество аргументов).Но как только B::showMsg объявлен виртуальным, все производные методы становятся виртуальными и должны иметь один и тот же прототип.

...