ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

在SystemVerilog中,类成员的private, public, protected 属性分别是什么意思,SystemVerilog的类中,成员变量默认是public还是private?

2022-09-07 19:00:19  阅读:291  来源: 互联网

标签:disp addr packet class private eth local public SystemVerilog


默认情况下,可以使用类的对象句柄从类外部访问类的成员和方法,即它们是public的。

如果我们不希望某些成员和某些方法可以从类外部访问怎么办?为了防止意外修改类成员/方法。,我们希望将类的成员设置为没有外部类(甚至是其子类)可以访问。

例如在大型项目中,我们可能会使用外部提供的“基”类库(如 UVM )。该第三方基类库需要确保其用户不会意外更改/覆盖类的成员和方法,这会对项目的其余部分产生严重的连锁反应。

封装:将数据隐藏在类中并仅通过类中方法使其可访问的技术称为封装。

换句话说,封装是创建数据容器及对其进行操作的相关方法。

有两种方法可以隐藏类中的数据。它们是通过在类成员前面加上以下关键字来实现的:

  •   local(private)
  •        protected

LOCAL

local成员在类外不可见,扩展/派生类也不可见。类的本地方法可以访问这些本地成员。一个类的属性和方法都可以是“本地的”。使类成员本地化的关键字是 local。这是一个简单的例子:

class packet;
        local int addr; //local property
        local function void disp(input int data); //local method
           $display("data = %h", data);
           $display("addr = %h", addr); //access local property
        endfunction
endclass

module class_TOP( );
         initial begin
           packet p1;
           p1 = new( );
          // p1.addr = 'hff;
             //COMPILE ERROR - can't access 'local' property
          // p1.disp(20);
             //COMPILE ERROR - can't access 'local' method
          end
endmodule

在“packet”类中,我们定义了一个名为“addr”的“local”属性。由于这是本地的,因此它仅对类中的方法可见。我们还将函数“disp”声明为local方法。它可以访问本地属性“addr”。请注意,这个函数(“disp”)必须是local的才能访问local属性。

让我们举同样的例子,看看是否可以从扩展类访问“local”属性/方法:

class packet;
        local int addr;
        local function void disp(input int data);
           $display("data = %h", data);
           $display("addr = %h", addr); //access local property
         endfunction
endclass
class eth_packet extends packet;
         function set_addr;
           //addr = 'hff; //COMPILE ERROR -
           //can't access 'local' property from extended class
         endfunction
         function void eth_disp;
           //super.disp(50);//COMPILE ERROR -
           //can't access 'local' method from extended class
         endfunction
         function void disp(input int data);
         //OK to override 'local' method in extended class
           $display("From eth_packet data=%d", data);
         endfunction
endclass

module class_TOP( );
         initial begin
           eth_packet e1;
           e1 = new( );
           e1.disp(50);
         end
endmodule

此示例与上面的示例类似。但在本例中,我们将基类“packet”扩展为类“eth_packet”。在“eth_packet”中,我们尝试访问本地属性“addr”(属于“packet”类),会给我们一个编译错误。同样,当我们尝试访问类“packet”(来自“eth_packet”)的本地方法“disp”时,会得到编译错误。

然后我们在“eth_packet”类中覆盖本地方法“disp”(属于“packet”类)。在子类中覆盖父类的本地方法是可以的。

然后我们从模块“class_TOP”调用“eth_packet”的方法“disp”。

 

Protect

Protected修饰的类属性或方法具有local成员的所有特征,除了它可以被继承,它对扩展/派生类是可见的。

它们可以由扩展的子类访问,但不能从类外部访问。

让我们看一下与上面相同的示例,但将属性声明为“Protected“。我们将看到Protected属性和方法对扩展类是可见的——但在类之外是不可见的。另外,请注意,类中的Protected属性可以通过普通方法访问(即,这些方法不必是“Protected”):

class packet;
        protected int addr;
        protected function void disp(input int data);
          $display("From packet");
          $display("\t data = %h", data);
          $display("\t addr = %h", addr);
         endfunction
endclass

class eth_packet extends packet;
         function set_addr;
           addr = 'hff;
               //protected property 'addr' visible to extended class
         endfunction
         function void eth_disp;
           super.disp('hff);
                 //protected method 'disp' visible to extended class
         endfunction
         function void disp(input int data);
                 //OK to override 'protected' method in extended class
           $display("From eth_packet");
           $display("\t data = %h", data);
         endfunction
endclass

module class_TOP( );
         initial begin
           packet p1;
           eth_packet e1;
           e1 = new( );
           p1 = new( );
           //p1.disp(20); //COMPILE ERROR
           //protected methods 'disp' not visible outside the class
           e1.eth_disp;
           e1.disp('h ffff);
         end
endmodule

在这个例子中,我们在类“packet”中声明了一个Protected属性“addr”和一个Protected方法“disp”。在扩展类“eth_packet”中,我们访问属性“addr”。这没关系,因为基类的Protected属性对其扩展类是可访问/可见的。同样,我们从扩展类“eth_packet”访问方法“disp”(属于“packet”类)。这也可以,因为基类的Protected方法对其扩展类是可访问/可见的。

在模块“class_TOP”中,我们实例化了“packet”和“eth_packet”。但是,当我们尝试从模块“class_TOP”访问“packet”类的“disp”函数时,会出现编译错误。这是因为从类外部看不到Protected方法(或属性)。

最后,使成员成为local或Protected是一种很好的做法。这有助于我们之前讨论的数据隐藏。(封装)

总结问题:

public :公共的,被public关键字修饰的属性或方法,对子类以及外部类都是可见(可访问,调用)的

private(local), 本地的,私有的,被protected关键字修饰的属性或方法,对于子类以及外部类都是不可见的,不能被访问调用的

protected:受保护的,被protected关键字修饰的属性或方法,对于子类是可见的,对于外部类是不可见的。

 

在SV中,成员变量默认是public

标签:disp,addr,packet,class,private,eth,local,public,SystemVerilog
来源: https://www.cnblogs.com/fuqiangblog/p/16666878.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有