OOP术语:
类class:封装了数据和操作这些数据的子程序;
对象object:类的一个实例;
句柄handle:指向对象的指针;类似于一个对象的地址
属性property:储存数据的变量;
方法method:任务或函数中操作变量的程序性代码;
原型prototype:程序的头;包括程序名、返回类型和参数列表
声明句柄的时候,句柄被初始化为特殊值null;
在面向对象编程中,类具有以下三个主要特性:
封装(Encapsulation):封装是指将数据和操作数据的方法捆绑在一起的机制。类通过封装将数据和操作数据的方法组合成一个单一的单元,从而隐藏了数据的内部细节,只暴露出必要的接口供外部使用。这样可以提高代码的可维护性和安全性。
继承(Inheritance):继承是指一个类可以派生出子类,子类可以继承父类的属性和方法,并且可以添加新的属性和方法或者修改父类的方法。继承提供了代码重用的机制,可以减少重复编码,提高代码的可维护性和扩展性。
多态(Polymorphism):多态是指在不同的上下文中,同一个方法可以有不同的行为。通过多态,可以编写出通用的代码,可以处理多种不同类型的对象,而无需对每种类型都编写特定的代码。多态通过方法的重载和方法的覆盖来实现,提高了代码的灵活性和可扩展性。
构造函数new();
1.为类分配空间2.将变量初始化为默认值(二值变量为0,四值变量为x)3.保存返回对象的地址
最好将声明句柄和调用构建函数分开
全局变量和局部变量
全局变量是从仿真开始到结束一直存在的,例如module中的变量默认情况下全部为全局变量,这也可以理解为module中的变量是硬件电路中实际存在的信号和连接,所以它们是静态生命周期;
局部变量只在其定义的作用域内有效,在作用域结束时销毁,不会对其他部分产生影响
静态变量和动态变量
静态变量的特点:
该变量将被这个类的所有实例所共享,并且使用范围仅限这个类。
静态变量在声明时就应该对其初始化,它只初始化一次,也就是在仿真0时刻就存在。可以认为声明在类中的静态成员变量,它是保存在类中,而不是在对象中,它会一直存在的,不会因为对象被销毁而消失。静态变量可以在类没有被实例化的时候调用,通过 class::static_variable 的方式获取静态变量。
动态变量的特点:
动态变量是类在实例化时,即调用构造函数new( )才会初始化。它的声明周期随着对象而存在,当对象被销毁时,这个变量就也就消失了。必须要在类被实例化之后才可以调用。
静态方法和动态方法
static 和 automatic 除了可以修饰类中的成员变量,还可以修饰 function 和 task,被static修饰的方法称为静态方法。
静态方法的特点:
如果方法被static修饰,那么其内部所有的声明的变量都是 static 的;静态方法可以在类没有被实例化时被调用,通过 :: 操作符获取,具有全局的静态生命周期;如果方法被声明为static,那么在仿真开始时即会被创建,且可以被多个进程和方法共享;静态方法只能访问类的静态成员;
动态方法的特点:
如果方法被修饰为 automatic,那么其内部所有的声明的变量默认都是 automatic的;如果被修饰为 automatic,那么在进入该方法后,automatic变量会被创建,而离开该进程/方法后就被销毁;
在类之外定义方法:
![]() |
$root 是一个系统任务,用于获取设计中模块层次结构的顶层模块的实例名称
this 和 super的区别在于:
this 会先在当前作用域中查找,如果当前作用中没有,则会去上一级作用域中查找,知道找到该变量为止;
this 关键字用于引用当前对象的实例。
在一个类的方法内部,this 关键字指向调用该方法的对象。
可以使用 this 来访问当前对象的成员变量和方法。
super首先会先在该类的父类中查找。
在一个子类中,可以使用 super 来调用父类的构造函数或方法
在任务中修改句柄
![]() |
在程序中修改对象
![]() | ![]() |
用new操作符复制一个对象
当只拷贝对象中的成员变量和声明的句柄时,称为浅拷贝。
a2 = new a1; // a2浅拷贝a1
浅拷贝只把对象中的句柄复制了,却没有复制句柄b所指向的对象。这会导致复制后,a2中的句柄b 和 a1 中的句柄b指向同一个对象,如果a2中的句柄b修改了对象的内容,那么a1中的句柄 b 所指向的内容也会发生变化。
![]() | ![]() |
而深拷贝会复制对象中的所有成员变量以及对象中嵌套的其他类的实例的内容。
实现深拷贝,需要自己在类中定义copy方法,目的是为了在复制类中的套娃(对象里面另一个类的实例)时,产生一个新的句柄,并产生一个具有相同内容的对象。
将成员拷贝函数copy_data() 和新对象生成函数copy()分成两个方法,这样使得子类继承和方法复用
class basic_test;
int def;
int fin;
//只拷贝变量
virtual function void copy_data(basic_test t);
t.def = def;
t.fin = fin;
endfunction
//新对象生成函数
virtual function basic_test copy();
basic_test t = new();
copy_data(t);
return t;
endfunction
endclass
class son_test extends basic_test;
int ecl;
function void copy_data(basic_test t);
son_test h;
super.copy_data(t);
//因为这里父类的句柄t指向的是一个子类对象
//所以可以完成父类句柄——>子类句柄的强制转换
$cast(h,t);
h.ecl= this.ecl;//复制当前子类的成员变量
endfunction
function basic_test copy();
son_test t = new();//拷贝子类对象
//t是子类句柄,copy_data()需要传递一个父类句柄
//所以在这一步会有一个隐式的子类句柄转换为父类句柄的过程
copy_data(t);
return t;//注意:返回的是一个父类的句柄,但这个父类句柄指向的是一个子类的对象
endfunction
endclass
module tb;
son_test wr,h;
initial begin
wr = new();
//注意copy()会返回一个父类句柄
//所以想得到一个子类句柄需要做一个类型转换
h = wr.copy();
//这里wr和h指向的是两个不同的子类对象
//因为调用copy函数时,生成了一个子类对象
end
endmodule