在C ++之类的语言中,基于对象指针值调用虚拟方法。 Systemverilog LRM指定在使用虚拟方法的情况下,只有最新派生类中的方法才有效。
以下文字摘自LRM:
可以用关键字virtual标识类的方法。 虚方法是基本的多态构造。虚拟方法 应在其所有基类中覆盖一个方法,而 非虚拟方法只能覆盖该类及其中的方法 子孙。一种查看方式是,只有一种 每个类层次结构的虚拟方法的实现,它是 总是最新派生类中的一个。
我不知道如何解释这一说法。上面的陈述似乎表明,不管对象句柄值是多少,仅解析派生类中的最新定义。
我尝试了LRM中的示例,但结果与在其他语言(如C ++)中所期望的一样。这是代码:
class BasePacket;
int A = 1;
int B = 2;
function void printA;
$display("BasePacket::A is %d", A);
endfunction : printA
virtual function void printB;
$display("BasePacket::B is %d", B);
endfunction : printB
endclass : BasePacket
class My_Packet extends BasePacket;
int A = 3;
int B = 4;
function void printA;
$display("My_Packet::A is %d", A);
endfunction: printA
virtual function void printB;
$display("My_Packet::B is %d", B);
endfunction : printB
endclass : My_Packet
BasePacket P1 = new;
My_Packet P2 = new;
initial begin
P1.printA; // displays 'BasePacket::A is 1'
P1.printB; // displays 'BasePacket::B is 2'
P1 = P2; // P1 has a handle to a My_packet object
P1.printA; // displays 'BasePacket::A is 1'
P1.printB; // displays 'My_Packet::B is 4' – latest derived method
P2.printA; // displays 'My_Packet::A is 3'
P2.printB; // displays 'My_Packet::B is 4'
end
我创建了一个小代码段进行测试,以某种方式,它与LRM所说的或dave_59似乎暗示的不匹配(除非我完全误解了)。
module x;
class B1;
virtual function void printme;
$display("Class B1");
endfunction : printme
endclass : B1
class B2 extends B1;
virtual function void printme;
$display("Class B2");
endfunction : printme
endclass : B2
class B3 extends B2;
virtual function void printme;
$display("Class B3");
endfunction : printme
endclass : B3
B1 b1_handle = new;
B2 b2_handle = new;
B3 b3_handle = new;
initial begin
b1_handle.printme;
b1_handle = b2_handle;
b1_handle.printme;
b1_handle = b3_handle;
b1_handle.printme;
end
endmodule
以下是输出:
B1级B2级B3级
因此,执行基于句柄的值,而不是虚拟方法的最新实现。例如,如果在打印B类时解决了最新的虚拟方法,则以下行应打印B3类。
b1_handle = b2_handle; b1_handle.printme;
顺便说一句,模拟器的行为方式恰好是我期望的方式。这种期望是基于我在C ++中看到的。只有LRM中的陈述使我感到困惑。
答案 0 :(得分:0)
SystemVerilog的OOP模型来自Java(两者均来自Sun Microsystems的工作开发)。对于虚拟方法,这与C ++相同。
SystemVerilog LRM符合您的理解,但是如果您考虑足够长的时间,则表示方式会稍有不同。