在SV中,cast作为一个显示的转换方法,一个重要的应用就是在类继承过程中实现类型的向下转换;
向上转换:将扩展类句柄(child_handle) 赋给 父类(father_handle)
father_handle = child_handle
向下转换 :将父类句柄(father_handle) 赋给 扩展类(child_handle)
child_handle = father_handle在SV中,编译允许基类句柄指向子类对象,这是合法的;但是不允许子类句柄指向基类对象,这样可能会造成数据的丢失,是不合法的,在SV编译时会检查句柄类型,会报错。
类型向下转换需要使用cast,cast是检查对象类型,而不是检查句柄类型。
实验代码:
class father;
string m_name;
function new(string name);
m_name = name;
endfunction
function void print();
$display("HELLOW %s",m_name);
endfunction
endclass:father
class child0 extends father;
string car="car";
function new(string name);
super.new(name);
endfunction
endclass:child0
class child1 extends father;
string plane="plane";
function new(string name);
super.new(name);
endfunction
endclass:child1
module top;
father f;
child0 c0;
child1 c1;
child1 c2;
initial begin
f=new("father");
f.print();
c0=new("child0");
f=c0;
f.print();
c1=new("child1");
f=c1;
f.print();
c1.plane="big_plane";
$cast(c2,f);
f.print();
$write(",has %s", c2.plane);
end
endmodule:top
仿真结果:
代码解析:
f=new("father");//为父类开辟空间,此时m_name为father
f.print(); //调用函数print 打印Hellow father
c0=new("child0");//为child0子类开辟空间,此时car=car,m_name=child0;
f=c0;//父类句柄指向子类child0对象,父类car=car,m_name=child0;
f.print();//调用函数print打印Hellow child0
c1=new("child1");//为child0子类开辟空间,此时plane=plane,m_name=child1;
f=c1; /父类句柄指向子类child0对象,父类plane=plane,m_name=child1;
f.print();//调用函数print打印Hellow child1
c1.plane="big_plane";//显式将c1.plane赋值为big_plane,此时父类f.plane也赋值为big_plane
$cast(c2,f);//将c2悬空的句柄指向c1,c2.plane=big_plane,m_name=child1
f.print();//调用函数print打印Hellow child1
$write(",has %s", c2.plane);//打印,has big_plane
打印结果:
上边的练习做完了,但是cast的魅力你真的有感受到吗?可能还真没有,那就让我们通过下边的代码再细细感受一下cast到底做了什么,她的魅力究竟在何处!
首先进行一个简单的代码修改:
class father;
string m_name;
function new(string name);
m_name = name;
endfunction
function void print();
$display("HELLOW %s",m_name);
endfunction
endclass:father
class child0 extends father;
string car="car";
function new(string name);
super.new(name);
endfunction
endclass:child0
class child1 extends father;
string plane="plane";
function new(string name);
super.new(name);
endfunction
endclass:child1
module top;
father f;
child0 c0;
child1 c1;
child1 c2;
initial begin
f=new("father");
f.print();
c0=new("child0");
f=c0;
f.print();
c1=new("child1");
f=c1;
f.print();
$display("f.plane=%s",f.plane);
//c1.plane="big_plane";
//$cast(c2,f);
//f.print();
//$write(",has %s", c2.plane);
end
endmodule:top
修改内容:
去掉cast代码,加入一行代码: $display("f.plane=%s",f.plane);
要求打印出 f.plane;
编译结果会报错:
这是因为在SV编译时会检查句柄类型,而不是对象类型,会报错。所以就出现了练习的代码,使用cast进行对象转换,再对子类变量进行访问;
可能有的小伙伴还是很迷茫,为什么要进行两部操作,直接通过c1去访问不就好了,有什么应用场景呢?由于博主实际项目经验较浅,这部分内容待后续补上,感兴趣的小伙伴可以自己去搜一下,或者已经了解的小伙伴,也可以分享出来哦,大家一起进步!