https://blog.csdn.net/seabeam/article/details/47841539

在UVM中经常可以看到$cast的身影,这是SV的build-in task之一,当然它还有function的版本,这里不讨论。说到这,不得不提到“类型转换”这个术语,SV和很多其他语言一样,都支持特定类型间的相互转换。SV类型转换分两种方法,一种叫静态类型转换,另一种称之为动态类型转换。静态类型转换的语法类似为:

int a = 2;
    real b;
    b = real'(a);

这种静态类型转换一般是不会检查转换是否合法的,因此具有一定的危险性。但是$cast的task却不是这样,它在运行时将进行类型检查,如果转换失败,会产生运行时错误。

$cast可以对不同的内建类型进行转换,用的更多的是不同层次之间类的转换。在这种父类于子类之间的转换里, 父类站的高,子类在底下,从父类向子类的转换,称为向下类型转换,而子类向父类的转换称为向上类型转换。向上类型转换是安全的,而反之则是不安全的。原因在于子类既然继承了父类,就拥有父类的一切属性,除此之外,子类还有自己独特的个性,这些是父类没有的。当进行向上类型转换时,相当于父类的句柄指向子类对象,这样的话句柄仍然能对子类对象与父类相同的属性进行访问。但是反过来,如果向下类型转换也那么自由,当试图把子类的句柄指向父类的对象会发生什么呢?父类本来在内存里就划好了一小块地盘,但是因为子类含有比父类更丰富的属性,它很有可能会访问父类并不包含的资源,越界了。父类就好像北京的行政区域,子类非要去访问到河北的地界,河北就不同意了,手机还得算个漫游。这就会造成严重的内存溢出,所以向下类型是需要有严格的类型检查的,阻止非法转换。

很多人看到上面的话不止一次了,但是却不知道什么情况下向下类型转换才会成功。来看一个例子,父亲有两个孩子,孩子0有辆车,而孩子1有架飞机

class father;
      string m_name;
     
      function new (string name);
        m_name = name;
      endfunction : new
     
      function void print ();
        $display("Hello %s", m_name);
      endfunction : print
    endclass : father
     
    class child0 extends father;
      string car = "car";
     
      function new (string name);
        super.new(name);
      endfunction : new
    endclass : child0
     
    class child1 extends father;
      string plane = "plane";
     
      function new (string name);
        super.new(name);
      endfunction : new
    endclass : child1

现在来小试牛刀:

module top;
      father f;
      child0 c0;
      child1 c1;
      child1 c2;
     
      initial begin
        f = new("father");
        f.print();
        c0 = new("child0");
        f = c0;
        f.print();
        c1 = new("child1");
        f = c1;
        f.print();
      end  
    endmodule : top

这里的child赋值给father的语句全部都是向上类型转换,是安全的,因此直接用=号就能进行转换,最后打印出来的结果是:

father
    child0
    child1

假如说反过来,我们这样:

c1 = f;

或者使用了$cast但是指向对象类型和想转换的类型有区别:

$cast(c0, f);

都是会失败的。只有当前父类指针指向的对象和待转换对象的类型一致时,cast才会成功。我们把上面的代码改一改:

initial begin
        f = new("father");
        f.print();
        c0 = new("child0");
        f = c0;
        f.print();
        c1 = new("child1");
        f = c1;
        f.print();
     
        c1.plane = "J10";
     
        $cast(c2, f);
        c2.print();
        $display("has %s", c2.plane);
      end

这时候转换成功,因为c1和c2的类型是相同的。这里玩了个小动作,把c1的plane换成了歼十,打印出来的结果:

Hello father
    Hello child0
    Hello child1
    Hello child1
    has J10

千万小心这样的句柄传递,会造成两个句柄同时指向一个对象,当使用其中一个句柄对对象的内容进行修改,另一个句柄再次访问的时候就会发现值已经被改变了。同时也可以看出cast的复制效果只是个shadow copy, 这就是为什么UVM的copy函数在$cast之后还要再对对象里的属性进行逐个取出来赋值的原因,这样的deep copy才能从根本上阻断源和目的的联系。

那么这样的类型转换有什么好处呢?通常的类型转换是一种格式的需求,但是继承类之间的相互转换,却有更多的便宜。将独特的子类转换为父类的类型,更注重通用性,共性越多,重用性越好。就好像你从宿舍去教室,他从宿舍去食堂,你们到大门这截路大家都能走。但是终究还是要分道扬镳,这时候要处理具体的内容就需要将父类句柄类型转换为子类类型才能访问子类特有的资源。
---------------------
作者:seabeam
来源:CSDN
原文:https://blog.csdn.net/seabeam/article/details/47841539
版权声明:本文为博主原创文章,转载请附上博文链接!

cast的更多相关文章

  1. C++ cast

    excerpted from Type conversions K&R Section 2.7 p59 对type conversion 的解释: The precise meaning of ...

  2. Java-Spring:java.lang.ClassCastException: com.sun.proxy.$Proxy* cannot be cast to***问题解决方案

    java.lang.ClassCastException: com.sun.proxy.$Proxy* cannot be cast to***问题解决方案 临床表现: 病例: 定义代理类: @Tra ...

  3. SSH整合时执行hibernate查询报错:java.lang.ClassCastException: com.ch.hibernate.Department_$$_javassist_0 cannot be cast to javassist.util.proxy

    今天在整合ssh三个框架时,有一个功能,是查询所有员工信息,且员工表和部门表是多对一的映射关系,代码能正常运行到查询得到一个List集合,但在页面展示的时候,就报异常了, java.lang.Clas ...

  4. CAST function should support INT synonym for SIGNED. i.e. CAST(y AS INT)

      Login / Register Developer Zone Bugs Home Report a bug Statistics Advanced search Saved searches T ...

  5. Java Class.cast方法

    1.Java api public T cast(Object obj); Casts an object to the class or interface represented 解释的比较笼统, ...

  6. SELECT CAST(GETDATE() AS VARCHAR(10)) 显示不同格式的原因

    开发人员测试时,发现生产服务器与测试服务器执行SELECT CAST(GETDATE() AS VARCHAR(10))语句显示的格式不一样.如下所示 Server A Server B 其实出现这个 ...

  7. 【MySQL】使用Length和Cast函数计算TEXT类型字段的长度

    背景: 前段时间,业务需要,为了快速让解析的Excel入库,所以把不是很确定的字段全部设置成了TEXT. 今天需要进行表结构优化,把字段长度控制在合适的范围,并尽量不使用TEXT类型. -- 计算长度 ...

  8. sql 中convert和cast区别

    SQL中的cast和convert的用法和区别 更多 来源:SQL学习浏览量: 学习标签: cast convert sql 本文导读:SQL中的cast 和convert都是用来将一种数据类型的表达 ...

  9. postgres 类型转换 cast 转

    转自: http://blog.csdn.net/yufenghyc/article/details/45869509 --1 例子postgres=# select 1/4; ?column? -- ...

  10. 错误 java.lang.ClassCastException: com.ylpw.sms.YZZYSenderUtil cannot be cast to ResourceBundle

    出现错误: java.lang.ClassCastException: com.ylpw.sms.YZZYSenderUtil cannot be cast to ResourceBundle 百度搜 ...

随机推荐

  1. 2018.4.26 lvm

    lvm(Logical Volume Manager)逻辑卷管理,是Linux环境下对磁盘分区进行管理的一种机制. 基本概念: 1. 物理卷-----PV(Physical Volume)物理卷在逻辑 ...

  2. 【python接口自动化-requests库】【二】requests库简单使用(入门)

    一.post请求 前面讲了,我们get请求的时候,引入requests的包,然后直接使用get方法,那么post是不是一样的? 1.首先我们先引入requests import requests 2. ...

  3. Redis使用规范

    突出强调部分 [强制]key名不要包含特殊字符,如空格.换行.单双引号以及其他转义字符 [强制]拒绝bigkey(防止网卡流量.慢查询) [强制]控制key的生命周期,redis不是垃圾桶 [强制]技 ...

  4. go环境变量与sublime Text3开发工具

    环境:win7   1:下载安装包 (下载太慢了,上传至百度网盘了) 链接:https://pan.baidu.com/s/10wHOR01mW-kjdkynqu1F-g 密码:kv71   2:安装 ...

  5. DL服务器主机环境配置(ubuntu14.04+GTX1080+cuda8.0)解决桌面重复登录

    DL服务器主机环境配置(ubuntu14.04+GTX1080+cuda8.0)解决桌面重复登录 前面部分是自己的记录,后面方案部分是成功安装驱动+桌面的正解 问题的开始在于:登录不了桌面,停留在重复 ...

  6. linux-linnode满了的提示

    线上有一台web服务器磁盘检测告警了,提示空间不足,登到服务器查看 <ignore_js_op> touch:cannot touch `furm.html': No space left ...

  7. 问题 Windows7VMware14安装虚拟机时出现 此主机不支持虚拟化实际模式。需要具备 Intel“VMX 不受限客户机”功能才能在 Intel 处理器上运行此虚拟机。 模块“CPUIDEarly”启动失败。

    问题 Windows7VMware14安装虚拟机时出现 此主机不支持虚拟化实际模式.需要具备 Intel“VMX 不受限客户机”功能才能在 Intel 处理器上运行此虚拟机. 模块“CPUIDEarl ...

  8. CentOS7版本区别和下载

    CentOS 7提供了三种ISO镜像文件的下载: DVD ISO 标准安装版,一般下载这个就可以了(推荐) Everything ISO 对完整版安装盘的软件进行补充,集成所有软件.(包含centos ...

  9. Git-撤销(回退)已经add,commit或push的提交

    本文只阐述如何解决问题,不会对git的各种概念多做介绍,如果有兴趣可以点击下面的链接,进行详细的学习:Pro Git本文适用的环境 现在先假设几个环境,本文将会给出相应的解决方法:1. 本地代码(或文 ...

  10. 6、 (★、※)root that results in a highest tree

    问题:对于一棵特定的树,选择合适的根结点,使得树的高度最大. 思路: 先选择一个结点,从该结点开始遍历整棵树,获取能达到的最深的顶点(记为结点集合A): 然后从集合A中任意一个结点出发遍历整棵树,获取 ...