类的多态:OPP中多个子程序使用一个共同名字的现象
虚方法可以实现动态查找,实现基类句柄调用子类的方法(子类句柄可以直接赋值给父类句柄);
而父类句柄完成调用子类成员变量,只有通过句柄转换才可以实现,因为编译器在编译时候做静态检查,不允许将父类句柄直接赋值给子类,所以做动态检查和转换$cast(子类句柄,父类句柄)
class animal;//父类
int age=-1;//变量
function new(int a);//方法,new函数分配空间
age = a;
endfunction : new
virtual function void make_sound();//虚函数
$fatal(1, "Generic animals don't have a sound.");
endfunction : make_sound
endclass : animal
class lion extends animal;//子类
function new(int age);
super.new(age);//调用父类animal中函数并将age传入
endfunction : new
function void make_sound();
$display ("The Lion says Roar");
endfunction : make_sound
endclass : lion
class chicken extends animal;//子类
function new(int age);
super.new(age);
endfunction : new
function void make_sound();
$display ("The Chicken says BECAWW");
endfunction : make_sound
endclass : chicken
module top;
initial begin
lion lion_h;//声明子类lion的句柄
chicken chicken_h;//声明子类chicken的句柄
animal animal_h;//声明父类animal的句柄
lion_h = new(15);//继承到age数据成员,new方法将age传递到animal构造函数
lion_h.make_sound();/重载make_sound()函数
$display("The Lion is %0d years old", lion_h.age);
chicken_h = new(1);
chicken_h.make_sound();
$display("The Chicken is %0d years old", chicken_h.age);
animal_h = lion_h;//基类句柄指向扩展对象
animal_h.make_sound();//根据对象类型决定调用什么方法,所以调用方法是lion::make_sound
$display("The animal is %0d years old", animal_h.age);
animal_h = chicken_h;
animal_h.make_sound();//调用chicken::make_sound
$display("The animal is %0d years old", animal_h.age);
end
endmodule : top
编译仿真运行后结果为
The Lion says Roar
The Lion is 15 years old
The Chicken says BECAWW
The Chicken is 1 years old
The Lion says Roar
The animal is 15 years old
The Chicken says BECAWW
The animal is 1 years old
小结一下:
虚方法:通过父类句柄调用子类方法,动态绑定,父类句柄在调用方法时确定自身指向的对象的类型,进而再调用正确的方法
动态转换:通过父类句柄访问子类成员,可将父类句柄成功赋值给子类句柄,通过子类句柄访问子类对象中的成员和方法。子类句柄访问父类成员则通过super来实现。