多态行为
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
在变体 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::showMsg
是 virtual,那么 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);
有人可以帮助解释这种行为差异吗?虚拟函数不应该总是虚拟的吗?产地有关系 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
在变体 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::showMsg
是 virtual,那么 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);