目录
clone方式1
注意:类的多态,父类和子类同名函数必须保持(函数名一致,参数类型一致,返回类型一致)。
父类clone()是产生一个父类对象,子类clone()产生一个子类对象。
父类与子类clone()的返回值都是父类句柄!
class trans;
bit[31:0] data[];
int pkt_id;
int data_nidles;
int pkt_nidles;
bit rsp;
function trans clone(trans t = null); //传进来的都是父类句柄
if(t == null) t = new();
t.data = data;
t.pkt_id = pkt_id;
t.data_nidles = data_nidles;
t.pkt_nidles = pkt_nidles;
t.rsp = rsp;
return t;
endfunction
endclass
class chnl_trans extends trans;
int ch_id; // new member in child class
//clone function-1
function trans clone(trans t = null); //传进来的都是父类句柄
chnl_trans ct;
if(t == null)
ct = new();
else
void'($cast(ct, t)); //为了父类句柄指向子类对象,将父类句柄转化为子类句柄
ct.data = data;
ct.pkt_id = pkt_id;
ct.data_nidles = data_nidles;
ct.pkt_nidles = pkt_nidles;
ct.rsp = rsp;
ct.ch_id = ch_id; // new member
return ct;
initial begin: member_override
trans t1, t2;
chnl_trans ct1, ct2;
wait(b_member_override == 1); $display("b_member_override process block started");
ct1 = new();
ct1.pkt_id = 200;
ct1.ch_id = 2;
// t1 pointed to ct1's trans class data base
t1 = ct1;
// t2 copied ct1's trans class data base
t2 = ct1.clone();
void'($cast(ct2, t2));
$display("hahah ct1.pkt_id=%d",ct2.pkt_id);
$display("hahah ct2.ch_id =%d",ct2.ch_id);
- 1.子类中function trans clone(trans t = null);
- 2.先进来父类句柄(trans t = null),
- 3.利用void'($cast(ct, t));将父类句柄转换成子类句柄
- 4.利用子类句柄可以访问父类和子类成员,
- 5.最后返回把子类句柄返回(return ct)
- 6.这时ct会隐形转换为父类句柄,因为子类中function trans clone(trans t = null)中的trans是返回类型,属于父类;
第3步:如果父类句柄不转化子类句柄(注释掉else void'($cast(ct, t)));并将ct换成t,那么只能成功复制t.data = data;
t.pkt_id = pkt_id;
t.data_nidles = data_nidles;
t.pkt_nidles = pkt_nidles;
t.rsp = rsp;
不能复制t.ch_id = ch_id;因为父类句柄访问不到ch_id,具体可见仿真
clone方式2
利用super.clone(ct),句柄传递进来交给父类,相当于运行父类中function trans clone(ct);即将子类对象里的父类变量都拷贝一遍给到ct指向的子类对象的成员变量。
//clone function-2
function trans clone(trans t = null);
chnl_trans ct;
if(t == null)
ct = new();
else
void'($cast(ct, t));
void'(super.clone(ct)); //解决父类成员拷贝
ct.ch_id = ch_id; // new member //解决子类成员拷贝
return ct;
endfunction
// void'(super.clone(ct));代替了以下代码
// ct.data = data;
// ct.pkt_id = pkt_id;
// ct.data_nidles = data_nidles;
// ct.pkt_nidles = pkt_nidles;
仿真
1、66行创建第一个子类对象;在左侧locals栏中可以看出ct1指向子类(@chnl_trans)创建的第一个对象(@1),它里面包括父类的成员部分,子类对象。
2、70行t1指向子类对象,仅代表与ct1指向相同对象,不代表可以访问到ch_id,仅可以访问父类成员。
3、几类错误分析
失败:打印 t1.ch_id会在编译时报错,t1指向子类对象但是不能找到ch_id
失败:打印 t2.ch_id会在编译时报错,t2指向子类对象但是不能找到ch_id
t1 = ct1;
// t2 copied ct1's trans class data base
t2 = ct1.clone();
void'($cast(ct2, t2));
$display("hahah t2.pkt_id=%d",t2.pkt_id);
$display("hahah t2.ch_id =%d",t2.ch_id);
失败 : ct2 = ct1.clone(); 父类句柄不能给子类句柄
ct2 = ct1.clone();
成功:$cast(ct2, t2) 利用$cast将父类句柄转化为子类句柄,ct2指向t2所指对象,实现子类句柄指向子类对象,可以访问ct2.ch_id。
initial begin: member_override
trans t1, t2;
chnl_trans ct1, ct2;
wait(b_member_override == 1); $display("b_member_override process block started");
ct1 = new();
ct1.pkt_id = 200;
ct1.ch_id = 2;
// t1 pointed to ct1's trans class data base
t1 = ct1;
// t2 copied ct1's trans class data base
t2 = ct1.clone();
void'($cast(ct2, t2));
$display("hahah ct1.pkt_id=%d",ct2.pkt_id);
$display("hahah ct2.ch_id =%d",ct2.ch_id);