【路科V0】systemVerilog基础8——对象拷贝

本文介绍了面向对象编程中的句柄概念,强调了对象与句柄的区别,以及句柄拷贝与对象拷贝的差异。讨论了浅拷贝和深拷贝,指出SV中的new()函数仅支持浅拷贝。此外,还阐述了数据隐藏和封装的重要性,通过local和protected关键字控制成员访问权限,以增强代码的维护性和兼容性。
摘要由CSDN通过智能技术生成

句柄的传递

        在区分了类(抽象)对象(具体)之后,初学者还需要区分对象(存储空间)句柄(空间指针)。也就是说,在创建了对象之后,该对象的空间位置不会更改,而指向该空间的句柄可以有多个。

        创建对象后,还需要句柄去索引到它。

Transaction t1, t2;//声明Transaction类型的句柄t1,t2
t1 = new(); //例化第一个对象,将new()函数返回的句柄赋予t1
t2 = t1;//将t1的值赋予t2,即t1和t2指向同一个对象
t1 = new();//例化第二个对象,并将其句柄赋予t1
//t1和t2分别指向了不同的对象

赋值和拷贝

区分句柄的拷贝和对象的拷贝  

在例化对象的过程中,需要将句柄声明和对象例化加以区分 

声明变量和创建对象是两个过程,也可以一步完成。

//创建了第一个对象,用p1句柄来指向它
Packet p1;
p1 = new;

        如果将p1赋值给另外一个变量p2,那么依然只有一个对象,只是指向这个对象的句柄有p1和p2。

        以下p1和p2指向了两个不同的对象。

Packet p1;
Packet p2;
p1 = new;
//创建对象,同时拷贝
p2 = new p1;
//在创建第二个对象时,将p1句柄置于new函数之后,
//这表示创建对象的同时,还拷贝了p1指向对象的内容

        在创建p2对象时,将从p1拷贝其成员变量例如整数、字符串和句柄等,这种拷贝方式称为浅拷贝(shallow copy) 。 

类的引用和实例

默认情况下,声明类的变量,句柄没有指向对象 

          当你声明一个类的变量时,你只是在声明将来要指向某个该类的实例的句柄(指针),而默认情况下它们并不指向任何对象。

声明类,句柄指向对象
如果想要句柄指向对象,方法:

  • 通过new()函数来为其创建一个实例;
  • 将某个句柄赋值给另外一个句柄。 

         如果两个句柄指向同一个对象,其中一个句柄在修改了该对象的成员以后,那么另外一个句柄也将受到影响,因为它俩指向的是同一个对象。

拷贝对象(浅拷贝)

           如果想拷贝一个对象,那么可以使用new + handle(句柄)的形式。

  • 示例a情况,声明一个类的变量,默认情况下,句柄并不指向任何对象。
  • 示例b情况,两个句柄指向同一个对象
  • 示例c情况,拷贝一个对象(浅拷贝)

初学者经常容易出错的类的拷贝方式

atm_cell cell =new ;
atm_cell cells [$];
while (cells.size ()<10) begin
    cell.randomize () ;
    cells.push (cell) ;
end

代码的目的:

        把10个atm_cell类的句柄,放置到句柄队列cells中。

问题:

        队列cells中,有十个句柄,都指向同一个对象。

        在上下文中,new函数只调用了一次。while循环语句中,对cell句柄指向的对象做的随机化操作,和句柄的存放,都是针对同一个对象的句柄
如果要你修改,你准备怎么办?

        让对象的例化和句柄放入到while循环语句中,保证每次循环,都能例化新的对象和对句柄的赋值。最终才能满足,是个句柄指向十个不同的对象。
 

在SV中,对于对象的拷贝,只能针对对象中的成员变量。 

浅拷贝和深拷贝

举例 

两个类 rgb和pixel。pixel的成员变量里面还有rgb类句柄color

pixel类句柄dot指向pixel对象

pixel类的成员变量  句柄color指向了rgb对象。

class rgb;
    byte red;
    byte green ;
    byte blue;
endclass: rgb

class pixel;
    int x;
    int y ;
    rgb color ;
endclass: pixel

pixel dot = new ;

浅拷贝(shallow copy) :

如果利用new函数和dot句柄做对象拷贝。发生拷贝的是

dot指向对象的成员变量x、y、color。

因此,新的句柄指向新的pixel对象,但是它的成员变量color和dot的成员变量color都指向了同一个rgb对象

深拷贝(deep copy):

如果想要拷贝dot.color指向的对象(需要自定义copy方法)

在该方法中应该

  • 创建新的pixel对象
  • 拷贝x和y变量
  • 创建新的对象
  • 对color指向的对象也完成拷贝

        通过这种拷贝,使得两个句柄,指向不同的pixel对象,它们的成员变量color,也能够指向不同的rgb对象 

总结: 

        对于拷贝而言,如果对象中还有句柄,例如上图的pixel类包含color句柄,那么在利用new函数拷贝对象时,只能对color句柄做拷贝,而不会对其指向的对象再做拷贝,这种方式称之为浅拷贝(shallow copy) 。

        如果你想要对对象中的句柄指向的对象也做拷贝,即做递归的拷贝,那么这种方式称之为深拷贝(deep copy) 。
        SV利用new()函数只能做浅拷贝,用户需要自己定义深拷贝的函数才能实现该需求。

数据的隐藏和封装

        类的成员(变量/方法)默认情况下,即是公共属性的。这表示对于类自身和外部均可以访问该成员。
        对于商业开发,类的发布方会限制一些类成员的外部访问权限,继而隐藏类成员的更多细节。(即无法通过句柄访问对象全部的成员)
        这种方式也使得类的外部访问接口更为精简,减轻了类的维护工作量,也使得类在修改时便于与旧版本保持兼容。
        数据隐藏的方式使得类的测试和维护都变得更为简单。

限制访问成员的方式:

local: 

        对于成员的限定,如果使用local,则只有该类可以访问此成员,而子类或者外部均无法访问。

protected:
        对于成员的限定,如果使用protected,则表示该类和其子类均可以访问此成员,而外部无法访问。

示例: 

class Packet;
    local integer i ;//无法从外部访问packet成员变量i
    function integer compare (Packet other) ;
        compare = (this.i == other.i) ;
    endfunction
endclass
//要比较两个对象,就无法使用句柄来索引成员变量i
//先在类中定义函数compare,用它来完成对成员变量i的访问。继而完成两个对象的比较。
class clock
    local bit is_summer = 0 ;
    local int nclock = 6 ;
    function int get_clock ( ) ;
        if (!is_summer) return this.nclock ;
        else return this.nclock+1;
    endfunction
    function bit set_summer (bit s) ;
        this.is_summer = s ;
    endfunction
endclass
//函数get_clock和set_summer是clock 类提供给外部作为访问成员变量的接口
//无法通过句柄对is_summer和 nclock进行访问修改,可以通过接口函数访问修改
//类的开发者可以主要维护外部可以访问的接口函数
//如果nclock变量访问的外部逻辑发生了变化,我们也只需要更新get_clock函数,
//这样维护的重心回到了类本身,而调用该类方法的外部成员,并不需要修改已有的访问函数代码
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值