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

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

作者:互联网

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

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

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

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

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

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

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