1.当基类中没有使用虚方法
class Basic; //定义基类
int addr;
function new(int addr);
this.addr = addr;
endfunction
function display();
$display("\n[basic] addr = %0d\n",addr);
endfunction
endclass
class Sub extends Basic; //定义扩展类
int data ;
function new(int addr,data);
super.new(addr);
this.data = data;
endfunction
function display();
$display("\n[sub] addr = %0d, data = %0d\n",addr,data);
endfunction
endclass
module tb;
Basic b_handle;
Sub s_handle;
initial begin
s_handle = new(10,11); //new一个扩展对象
b_handle = s_handle; // 使基类句柄指向扩展对象
b_handle.display; //指向扩展对象的基类句柄,调用基类中的方法,而不是扩展类中的方法
end
endmodule
未使用virtual关键字时。指向扩展对象的基类句柄,调用基类中的方法,而不是扩展类中的方法,此时调用的是Basic::display。
2.当基类中使用虚方法(virtual)时
class Basic;
int addr;
function new(int addr);
this.addr = addr;
endfunction
virtual function display(); //基类中使用虚方法
$display("\n[basic] addr = %0d\n",addr);
endfunction
endclass
class Sub extends Basic;
int data ;
function new(int addr,data);
super.new(addr);
this.data = data;
endfunction
function display();
$display("\n[sub] addr = %0d, data = %0d\n",addr,data);
endfunction
endclass
module tb;
Basic b_handle;
Sub s_handle;
initial begin
s_handle = new(10,11);
b_handle = s_handle;
b_handle.display;
end
endmodule
当决定调用虚方法时,sv会根据对象的类型而非句柄的类型来决定调用什么方法,这里调用的就是 Sub::display。
3.直接将基类的句柄赋值给扩展类句柄是非法的
module tb;
Basic b_handle;
Sub s_handle;
initial begin
b_handle = new(10);
s_handle = b_handle;//将基类句柄赋值给扩展类句柄
s_handle.display;
end
endmodule
4.使用$cast将基类句柄赋值给扩展类句柄
4.1 当$cast里句柄所指向的对象不是同一类型,编译报错,赋值不用成功。
module tb;
Basic b_handle;
Sub s_handle;
initial begin
b_handle = new(12);
//b_handle指向基类对象,s_handle是扩展类的句柄,二者不兼容
$cast(s_handle,b_handle);
s_handle.display;
end
endmodule
4.2 $cast会检查句柄所指向的对象,只有源对象和目的对象是同一类型,才能赋值成功。
class Basic;
int addr;
function new(int addr);
this.addr = addr;
endfunction
function display();
$display("\n[basic] addr = %0d\n",addr);
endfunction
endclass
class Sub extends Basic;
int data ;
function new(int addr,data);
super.new(addr);
this.data = data;
endfunction
function display();
$display("\n[sub] addr = %0d, data = %0d\n",addr,data);
endfunction
endclass
module tb;
Basic b_handle;
Sub s_handle,s_handle1; //定义两个不同的扩展类句柄
initial begin
b_handle = new(12); //基类句柄new一个对象
s_handle = new(10,11); //扩展类句柄new一个对象
b_handle = s_handle; //扩展类句柄赋值给基类句柄,基类句柄指向扩展类对象
$cast(s_handle1,b_handle);//从基类句柄中拷贝扩展对象的地址给另一个扩展类句柄
s_handle1.display; //扩展类句柄指向扩展对象调用Sub::display
b_handle.display; //基类句柄调用 Basic::display
end
endmodule