面向过程和面向对象的区别?
面向过程:
就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
把大象装进冰箱需要几步?
按照面向过程思想:
第一步:工作人员去打开冰箱门
第二步:把大象塞进冰箱
第三步:工作人员把冰箱门关上
面向过程就是把一件事按步骤一步一步来实现
用代码表示
public void openDoor(){} //开门
public void putIn(){} //装冰箱
public void closeDoor(){} //关门
面向对象:
对象,就是对问题中的事物的抽象,面向对象就是把现实中的事物都抽象为“对象”。每个对象是唯一的,且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。
例如在这个事件中:
冰箱作为一个对象;
大象作为一个对象。
冰箱有这些功能:开门、装物体、关门
class fridge{
public void open(大象){} //开门
public void putIn(大象){} //放进冰箱
public void close(大象){} //关门
}
class elephant{
public void eat(){} //吃
}
每个对象是独立的,有属于它自己的功能,只需要专心实现自己的功能就好。所以在建立对象模型阶段,仅仅关注对象有什么的功能,但不考虑如何实现这些功能。
如何理解OOP——面向对象编程?
OOP使用户能够创建复杂的数据类型,并且将它们跟使用这些数据类型的程序紧密的结合在一起,用户可以在更加抽象的层次建立测试平台和系统级模型。同时会提高代码的层次结构和复用性。
OOP的三大特性:封装、继承、多态
class和module的区别?
class | module |
变量在仿真的任何时刻可以构造或销毁 | 模块从仿真开始就确定 |
变量默认都是动态的 | 变量默认都是静态的 |
可以封装,继承,类里的变量默认是public类型,可以添加受保护类型(protected)和私有类型(local) | 模块不能封装和继承,模块内的变量是对公共开放的 |
类可以在module,interface,program,package中定义 |
编写第一个类
类封装了数据和操作这些数据的子程序,
创建新的对象
- verilog中也有例化的概念,比如verilog中的一个模块,是代码被编译时例化的,verilog的例化是静态的,就像硬件在仿真时不会变化,只有信号值在改变。
- sv中,例化是动态的,而且是在需要的时候才会被创建。产生的对象在使用过后,占用的内存会被释放,以供新的对象使用。
sv中的句柄
Transaction tr;// 声明一个句柄b
tr=new(); //调用new()函数创建一个对象
Transaction是声明的类,tr是指向Transaction这个类的一个句柄。在声明句柄tr的时候,它被初始化为特殊值null,调用new()函数创建Transaction的一个对象,new()函数为Transaction分配空间,将变量初始化为默认值并返回保存对象的地址。
OOP术语
- 类(class):包含变量和子程序的基本构建块。Verilog中与之对应的是模块(module)
- 对象(object):类的一个实例,在Verilog中,需要实例化一个module才能使用
- 句柄(handle):指向对象的指针,一个OOP句柄就像一个地址。但是它保存在一个只能指向单一数据类型的指针中。
- 属性(property):类中定义的变量
- 方法(method):任务或者函数中操作变量的程序性代码
个人的理解:类就像建造一个房子前画好的图纸,是一个没有实体的抽象概念,而句柄表示房子的地址,句柄指向了要建造的房子的位置,而使用new()函数表示开始在这个地址上建造图纸对应的房子。房子中的各种物品(冰箱,洗衣机,电灯)是类中定义的各种变量,类中定义的各种方法是对这些变量的操作。
自定义new函数
new()函数除了分配内存之外,它还初始化变量。在默认情况下,它将变量设置成默认数值,二值变量为0,四值变量为X。可以通过自定义new函数将默认值设成想要的数据。但是new函数不能有返回值,因为它总是返回一个指向类对象的句柄,其类型就是类本身。
new()是class中默认自带的,也可以自定义new()函数。
class Transaction;
logic[31:0]addr,crc,data[8];
function new(logic[31:0]a=3,d=5);
addr=a;
foreach(data[i])
data[i]=d;
endfunction
endclass
带有参数的new函数
class Transaction;
logic [31:0] addr ='h10;
logic [31:0] crc, data[8] ; //开辟空间;
function new(logic [31:0] a=3, d=5);
addr = a;
foreach (data[i])
data[i]= d;
endfunction
endclass
initial begin
Transaction tr; //声明句柄
tr = new(10); // data uses default of 5
end
sv调用哪个new函数,与这个取决于赋值操作符左边的句柄类型,这个句柄指向哪个类就是用的哪个类的new函数
new()和new[]的区别?
- new()函数创建一个实例化的对象
- new[]建立了一个动态数组
对象和句柄的区别?
句柄是类的指针,通过声明一个句柄创建一个对象,在一次仿真过程中,句柄可能指向很多个对象。
静态变量
在sv中,可以在类中创建一个静态变量,该变量将被这个类的所有实例所共享,并且它的使用范围仅限于这个类。
count变量在声明时加了static关键字,表示为静态变量,用来保存创建的对象的数目。t1,t2是Transaction这个类的两个句柄。不管创建了多少个对象,静态变量count只存在一个。可以认为静态变量count保存在类中而非对象中。
变量id不是静态变量,所以实例化的每个对象都有属于自己的id。
使用id来区分不同的对象是很好的方法。
通过类名访问静态变量
可以使用类名加上:: 这是类作用域操作符
也可以通过句柄的方式访问静态变量,t1.count t2.count,两个值是一样的,因为count只有一个。
- 静态变量和类的定义相关,与实例化对象无关
- 静态变量常用于存储可变数据
- 静态变量被类的所有对象共享
静态变量的初始化
静态变量通常在声明时初始化,而不是在new()函数中初始化。因为每一个新的对象被实例化时都会调用new()函数,静态变量不能每次都被初始化。
静态方法
sv中使用静态方法访问静态变量,不允许静态方法读写非静态变量
类的方法
就是在类中定义的内部task或者function,类中的方法默认是自动存储,所以不必使用automatic修饰符。
虽然两个类中都有display这个function,但sv会根据句柄的类型调用所属的display方法。
在类之外定义方法
- 把task和function都写在类里面,显得类特别长,不便阅读,
- 可以把方法的原型定义放在类的内部,然后再开始处添加关键词extern
- 方法的程序体(过程代码)移至类的后面定义
如何理解this?
当使用一个变量名时,sv将先在当前作用域内寻找,接着在上一级作用域内寻找,直到找到该变量为止。但如果在类的很深的底层作用域,想引用类一级的变量,这时用this比较方便。
this就是指代当前的这个类。
待续
类的继承,父类,子类
virtual function
shallow copy,deep copy
virtual class
pure virtual function
……