【SystemVerilog】SV 继承与多态

1. 继承miscs

  • 被声明为local的数据成员或方法只能对自身可见,而对于外部和子类不可见;
  • 被声明为protecte的数据成员或方法,对外部不可见,对于自身和子类可见。
  • 我们知道一个类的对象被定义的时候是一个空的句柄, 当其构造函数被调用的时候才分配空间, 其句柄也指向该片空间的入口地址。 同样, 当一个派生类的对象被定义的时候, 它也是一个空句柄, 当其构造函数被调用的时候, 分配的空间不仅有来自父类的继承而来的数据和方法, 还有自己添加的部分; 其中新添加的数据成员和方法存储在独立的空间中, 保持与继承成员和方法的独立性。
基类与派生类对象空间分配

1.1 子类对象与父类对象的赋值

子类对象也是它们的父类对象的有效表示。 例如, 每一个 DerivedPacket对象都是一个完全合法的 Packet对象。 一个 DerivedPacket 对象可以赋值给一个 Packet的对象变量:

DerivedPacket lp = new;
Packet p = lp;

为此, 子类对象可以赋值给父类对象。 在这个过程中有两个需要注意的问题。
1 ) 如何处理一个子类对父类的赋值过程?
2) 如何访问和引用重写和新增的数据成员和方法?

其中, 赋值过程中遵循以下规则。

  • 子类对象是父类对象的有效表示, 可以赋值给父类对象。
  • 父类对象可以通过$cast 的方式尝试给子类对象赋值, 并判定是否赋值合法。

        在访问对象的过程中遵循一下规则: 通过父类的对象去引用在子类中重写的属性或方法, 结果只会调用父类的属性或方法; 通过子类对象可以直接访问重写的属性或方法; 在子类扩展过程中新增的属性和方法对于父类对象不可见; 子类可以通过super操作符访问父类中的属性和方法, 以区分于本身重写的属性和方法。

        一个子类的对象赋值给一个父类的对象是合法的; 而若一个父类对象直接赋值给子类对象就是不合法的, 但是假如一个父类对象指向的是一个子类对象,那么把该父类对象赋值给另外一个子类对象, 则是合法的。 为了检查一个父类对象对一个子类对象赋值是否合法, 我们可以使用动态的类型转换$cast。

1.2 构造函数调用

        一个子类在实例化的时候会调用其构造函数 new()为其分配空间。 在该函数中定义的任何代码执行之前,new()执行的第一个默认动作是调用其父类的构造函数 new() ,并且会沿着继承关系按这种方式一直向上回溯调用。 因此, 所有的构造函数会按正确的顺序调用执行, 它们都是起始于根基类并结束于当前的类。

构造函数的调用和执行

2. 虚方法和多态

        类中的方法在定义的时候通过添加virtual关键字来声明一个虚方法,虚方法是一个基本的多态性结构。虚方法可以重新其所有基类中的方法,然而普通的方法被重写后只能在本身及其派生类中有效。从另一个角度解释,每个类的继承关系只有一个虚方法的实现,而且是在最后一个派生类中。

一个方法在被重写的时候可以声明为虚方法; 一旦方法被声明为虚方法, 它在后续的继承过程中就永远是一个虚方法, 不管重写的时候是否使用virtual。 也就是说, 虚方法在其子类扩展、 重写的时候virtual可选的而不是强制的

        封装可以隐藏实现细节, 使得代码模块化, 继承可以扩展已存在的代码模块, 它们的目的都是为了代码重用, 而多态则是为了实现另外一个目的: 接口重用

实现了多态需要以下三个步骤:
1 在父类中定义虚方法。 如 BasePacket 类中的虚方法printB。
2 在子类中重写父类中的虚方法。 如My_Packet 中对printB的重写。
3 申明父类对象的变量 ( 如 P1) , 该变量既可以指向父类对象 ( 如P1自身) , 也可以指向子类对象 ( 如 P2) 。 当变量指向父类对象时, 调用的是父类方法; 当变量指向子类对象时, 调用的是子类同名方法。 为此, 当父类的对象指向不同的子类对象的时候, 虚方法( 如 printB) 可以表现出不同的实现方法, 而它们都可以通过统一的父类对象实现访问。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SystemVerilog多态(polymorphism)特性是指子类和父类之间多个子程序使用同一个名字的现象。当子类从父类扩展创建之后,子类就继承了父类的属性和方法,这是SystemVerilog继承特性。然而,要使用多态特性,需要遵循以下规则: 1. 子类的方法必须与父类的方法具有相同的名称和参数列表。 2. 子类的方法可以重写(override)父类的方法,即在子类重新定义方法的实现。 3. 子类的方法可以通过super关键字调用父类的方法。 4. 子类的方法可以通过this关键字调用自身的其他方法。 通过使用多态特性,可以在不同的子类对象上调用相同的方法,但实际执行的是各自子类的方法实现。这样可以提高代码的灵活性和可扩展性。 以下是一个示例代码,演示了SystemVerilog类的多态特性: ```systemverilog class Animal; virtual function void makeSound(); $display("Animal makes sound"); endfunction endclass class Dog extends Animal; function void makeSound(); $display("Dog barks"); endfunction endclass class Cat extends Animal; function void makeSound(); $display("Cat meows"); endfunction endclass module Test; initial begin Animal a; Dog d; Cat c; a = new; d = new; c = new; a.makeSound(); // 输出:Animal makes sound d.makeSound(); // 输出:Dog barks c.makeSound(); // 输出:Cat meows end endmodule ``` 在上述示例,Animal类是父类,Dog和Cat类是子类。它们都有一个名为makeSound的方法。通过创建不同的子类对象,并调用它们的makeSound方法,可以看到每个子类对象都执行了自己的方法实现,实现了多态特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值