systemverilog:virtual 关键字的用法
我在****上查询了systemverilog中关于virtual关键字的用法,发现了好多人都说了这么一句话:
virtual function/task:
用于OOP思想的继承使用。当定义了virtual时,在子类中调用某function/task,会先查找在子类中是否定义该function/task,如果没有定义该function/task,则在父类中查找。未定义virtual时,只在子类中查找,没有定义就是编译错误。
我觉得这句话说得太迷惑人了,会让初学者理解上出现偏差。
而且这句话:
“未定义virtual时,只在子类中查找,没有定义就是编译错误”
是完全错误的!
class前加不加virutal的区别很容易理解,下面我重点解释一下function前面加virtual和不加virtual的区别。(以下的代码没编译过,大家领会精神即可)。
场景1
class A 的call_disp() 和disp()声明时加入了virtual,class B没有直接声明call_disp(); 当第37行(子类B调用A的call_disp函数)开始执行时,打印的内容是:
I am B
场景2:
Class A 的call_disp() 声明时没有virtual, 同时disp()也没有加virtual; class B没有直接声明call_disp(); 当第37行开始执行时,打印的内容是:
I am A
场景3:
Class A 的call_disp() 声明时没有virtual, 但是disp()加了virtual; class B没有直接声明call_disp(); 当第37行只开始执行时,打印的内容是:
I am A
场景4:
Class A 的call_disp() 声明了virtual, 但是disp()没有加virtual; class B没有直接声明call_disp(); 当第37行只开始执行时,打印的内容是:
I am A
场景5
此场景是为了反驳:
“未定义virtual时,只在子类中查找,没有定义就是编译错误”
这一错误。
Class A 的call_disp() 和disp()没有加virtual; class B直接声明call_disp(),但没声明disp(); 当第37行只开始执行时,打印的内容是依旧是:
I am A
看到没有,根本没有什么编译错误。
场景6
Class A 的call_disp() 和disp()没有加virtual; class B直接声明call_disp()和disp(),但是call_disp()没有重写代码,而是使用super关键字直接继承父类中的call_disp();
当第37行只开始执行时,打印的内容还是:
I am A
惊不惊喜,意不意外!!!
总结
对于父类A,其中有两个函数: FunX和 FunY, 同时FunY调用了FunX;
子类B继承自A,如果B没有直接声明FunY,同时父类A中FunY又没有加入virtual, 同时B又修改了FunX;
那么,当B实例化后,调用FunY函数后,FunY调用的是没有修改过的FunX!B类的FunX算是白修改了
为了 避免这种情况,你只能在B类中,也把FunY也重新写一遍(不能用super关键字)。
所以,父类的function在声明时,最好都加上virtual,这样子类就可以不用直接声明父类中出现的函数,这样比较节省代码(这是好处之一)。