在SystemVerilog中,类成员的private, public, protected 属性分别是什么意思,SystemVerilog的类中,成员变量默认是public还是private?
作者:互联网
默认情况下,可以使用类的对象句柄从类外部访问类的成员和方法,即它们是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