1、是什么?
先弄明白几个概念:
1-1. 类型转换
- 类型转换分为
静态类型转换
和动态类型转换
- 静态类型转换例子
int a = 2;
real b;
b = real'(a); //将a的类型从int转换成real型
这种静态类型转换一般是不会检查转换是否合法的,因此具有一定的危险性。但是$cast的task却不是这样,它在运行时将进行类型检查,如果转换失败,会产生运行时错误。
- 动态类型转换的例子
parent_class pc;
child_class cc_1,cc_2;
pc=new();
cc_1=new();
cc_2=new(); //new()返回值为地址,get到子类地址
//$cast(cc_2,pc) //在此处做动态类型转换不成功
pc=cc_1; //a-先把把子类cc_1的指针给父类pc(cc_1类型转换成pc类型)
$cast(cc_2,pc) //b-再进行动态类型转换-成功,此时父类pc的指针给cc_2(pc类型转换为cc_2类型)
$cast(sc_2,pc) 是个函数,这个函数的返回值为检查pc类型转换成sc_2类型时是否成功,成功返回0(一般函数返回值都是0),不成功返回1。所以可以用来做判断。
1-2. 向下类型转换:
- 简单理解:就是父(类)传子(类)。父类站的高,子类在底下,从父类向子类的转换,称为向下类型转换
- 深入理解:如何理解"传"字?我的理解是把子类句柄传给父类,再深入点,
子类的指针
现在要指向父类
了。为什么提到指针?我认为这样好理解。 - 父传子属于继承,需要交税,不check会闹官司。
1-3. 向上类型转换:
- 简单理解:就是子(类)传父(类)。
- 深入理解:
父类的指针
要指向子类
。 - 向上类型转换是安全的。
- 子传父,属于孝顺,天经地义不需要check。
2、为什么?
2-1 为什么向下类型转换需要$cast()?
思考:
- 由于多态的存在,一个类的句柄可以指向父类,也可以指向子类。
- 先思考一个问题:子类如何使用父类的变量or方法?
- 子类使用父类变量,首先想到的是把父类指针给子类,这样子类可以直接使用父类内容,code如下:
class parent;
int a=1;
int b=2;
int c=3;
endclass:parent
class child extends parent;
int d=4;
endclass:child
module top;
initial begin
parent pc;
child cc_1,cc_2;
pc=new();
cc_1=new();
cc_2=new();
cc_2 = pc; // 子类句柄指向父类(这是错误的);
end
endmodule
- 图示如下:class parent 含有a,b,c 三个变量,class child是parent的子类,多一个变量d。
- 如果直接
cc_2 = pc;
赋值的话,现在cc_2里面是父类的地址pc,如果后边代码中出现cc_2.d
的代码,相当于pc.d
,父类里面是找不到d变量,这肯定有问题。 - 应该考虑加上一个check,如果get到的地址(父类地址or父类的其他子类地址),指向的类中含有d变量的话,转换成功。
- 这个check就是$cast()。
更改后code:
module top;
initial begin
parent pc;
child cc_1,cc_2;
pc=new();
cc_1=new();
cc_2=new();
$cast(cc_2,pc) //使用$cast将父类指针传给子类,仿真出错
end
endmodule
log
# ** Error: (vsim-3971) $cast to type 'class work.test_sv_unit::child'from 'class work. test _sv_unit::base' failed in file test.sv.
2-2 为什么上诉code中$cast(cc_1,pc)不成功?
思考:
- 此时虽然用了$cast()做check,但是你若调用
cc_2.d
相当于cc_2.d ->pc.d
,但是在父类pc中没有d这个变量,怎么办? - 你需要把一个含有d变量的’子类_1’指针传给父类,然后再把父类指针传给’子类_2’,code如下:
module top;
initial begin
parent pc;
child cc_1,cc_2;
pc=new();
cc_1=new();
cc_2=new();
pc=cc_1;
$cast(cc_2,pc) //使用$cast将父类指针传给子类,仿真成功
end
endmodule
- 不会报错,完美解决!
3、怎么用?
-
一直在想兜兜转转的这么麻烦的类型转换到底有什么具体应用?后来看了一位博主写的场景后恍然大悟
-
原义是:使用$cast的一种场景是将某些child class数据传递到其他同类child class中,并且接收类的开发人员甚至不知道传入的类是哪种子类,因此通常他会在接收类使用parent class来获取传入的数据,然后使用$cast将数据检查/传输到某些接收类中。
-
也就是说需要一个中间商处理一下,这个中间商就是父类。
-
那么不直接将childclass数据传递到child class呢?区别在于下面两张图
参考:http://www.nihao070.cn/systemverilog/239.html
以上内容仅是个人学习心得,欢迎指正。