system-verilog: 关于虚方法和多态

这个问题,总会弄混,这次把相关内容摘录出来,加深印象.

继承的一些基本规则:

  • 子类继承父类的所有数据成员和方法;
  • 子类可以添加新的数据成员和方法;
  • 子类可以重写基类中的数据成员和方法,也就是重写;
  • 如果基类的一个方法被重写,其必须保持和基类的原定义有一致的参数;
  • 子类可以通过super操作符引用父类中的方法和成员;
  • 被声明为local的数据成员或方法只能对自身可见,而对于外部和子类不可见;
  • 被声明为protected的数据成员或方法,对外部不可见,对于自身和子类可见.

对象空间分配

1.类的对象被定义的时候,只是一个空的句柄;当其构造函数被调用的时候,才分配空间,其句柄指向该片空间的入口地址;

2.派生类的对象被定义的时候,也只是一个空句柄,当构造函数

 

 

 

1.虚方法与多态

1.1 背景:

///////////////////////////////////////////////////////////////////////////////////////////////////

基类:

///////////////////////////////////////////////////////////////////////////////////////////////////

class Packet;

 task build_payld();

      $display("Packet payld");

 endtask

 

 task build_packet();

      ......

      build_payld();

      ......

 endtask

///////////////////////////////////////////////////////////////////////////////////////////////////

派生类:

///////////////////////////////////////////////////////////////////////////////////////////////////

class DerivedPacket extends Packet;

   task build_payld();

      $display("DerivedPacket payld");

   endtask

endclass

///////////////////////////////////////////////////////////////////////////////////////////////////

测试代码:

///////////////////////////////////////////////////////////////////////////////////////////////////

module poly1;

     DerivedPacket der=new();

     initial  der.build_packet();

endmodule

///////////////////////////////////////////////////////////////////////////////////////////////////

测试结果:

///////////////////////////////////////////////////////////////////////////////////////////////////

Packet payld

///////////////////////////////////////////////////////////////////////////////////////////////////

测试结果分析:

///////////////////////////////////////////////////////////////////////////////////////////////////

(1) 派生类对象在调用其build_packet过程中,会调用build_payld这个任务;而build_payld这个任务在父类扩展的过程中被重写过;

虽然这样,最终调用的build_payld仍是父类中的build_payld,而不是子类中的build_payld.

因为默认情况下,子类中重写的方法对于父类是不可见的.

(2) 派生类对象的空间分配分为两个部分,一部分来自父类的继承部分,一部分是重写或新增的部分.默认情况下,父类的方法是无法访问派生类的重写和新增部分的。假如希望重写的方法被父类看到,就需要依靠虚方法和多态.

system-verilog: 关于虚方法和多态_第1张图片

 

1.2虚方法

(1) 类中的方法可以在定义的时候通过添加virtual关键字来声明一个虚方法,虚方法是一个基本的多态性结构.

(2) 虚方法为具体的实现提供一个原型,也就是在派生类中,重写该方法的时候必须采用一致的参数和返回值.

(3) 虚方法可以重写其所有基类中的方法,然而普通的方法被重写后只能在本身及其派生类中有效。

(4) 每个类的继承关系只有一个虚方法的实现,而且是在最后一个派生类中。

system-verilog: 关于虚方法和多态_第2张图片

   system-verilog: 关于虚方法和多态_第3张图片

system-verilog: 关于虚方法和多态_第4张图片

      system-verilog: 关于虚方法和多态_第5张图片

(5) 在P1指向P2后,当P1.printA被调用的时候,程序会调用访问内存中类对象P2中P1的部分,而此时发现printA是一个普通方法,为此直接调用并结束访问;

(6) 在P1指向P2后,当P1.printB被调用的时候,程序同样找到类对象P2中P1的部分,此时发现printB是个虚方法,这时其会咨询系统,查看整个P2在定义的时候是否重写了该方法.系统发现在P2中(除了P1外),确实重写了该方法,为此,程序会直接调用P2重写的实现.

(7) 带有虚方法的类称为多态类.

你可能感兴趣的:(system-verilog: 关于虚方法和多态)