$cast()的个人理解

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

以上内容仅是个人学习心得,欢迎指正。

  • 21
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值