Question:
SystemVerilog是否支持向下类型转换(将基类对象转换为派生类对象)? 如果可以,怎么做?
以下downcast示例不起作用:
class base;
int a = 5;
endclass
class extend extends base;
int b = 1;
endclass
module test;
initial begin
base m_base;
extend m_extend;
m_base = new();
m_extend = new();
$cast(m_extend, m_base);
$display(m_extend.a);
end
endmodule
Answer: 是的,你可以downcast。 你的例子是正确的语法,它实际上编译通过。 但是,您收到runtime错误,因为downcast失败。在你的例子中强制转换失败,因为只有基类对象的句柄实际引用了派生类型的对象,才能成功向下转换。 你可以调用$ cast作为一个函数,它将返回一个布尔值,指示downcast是否成功。
下面给出正确的例子:
class animal;
function void eat();
endfunction
endclass
class dog extends animal;
function void bark();
$display("woof");
endfunction
endclass
class cat extends animal;
function void meow();
$display("meow");
endfunction
endclass
module test;
initial begin
dog a_dog = new();
cat a_cat = new();
animal animals[$];
animals.push_back(a_dog);
animals.push_back(a_cat);
foreach (animals[i]) begin
dog another_dog;
animals[i].eat();
if ($cast(another_dog, animals[i])) begin
$display("Found a dog!");
another_dog.bark();
end
end
end
endmodule
输出:
# Found a dog!
# woof
IEEE Std 1800-2012中关于Casting的描述如下:将子类型表达式分配给继承树(超类或表达式类型的祖先)中较高类类型的变量总是合法的。 将父类型的变量直接赋值给它的一个子类类型的变量应该是非法的。 但是,只要父类句柄指向与子类变量兼容的对象,就可以使用$ cast将父类句柄指定给子类类型的变量。
以下强制类型转换失败是因为父类对象不能作为子类对待。
m_base = new();
$cast(m_extend, m_base); // destination type != source object type
要正确地转换,源句柄的对象必须与目标类型兼容:
m_extend = new();
m_base = m_extend;
$cast(m_extend, m_base); // destination type == source object type
向下类型转换即使通过多级继承的类也可以工作。 下面的例子演示了一个基类句柄,该句柄指向将被转换为扩展类(孙类对象的父类)的孙类对象:
class ext_more extends extend;
int c;
endclass
initial begin
base m_base;
extend m_extend;
ext_more m_ext_more;
m_ext_more = new();
m_base = m_ext_more;
$cast(m_extend, m_base); // legal, casting a subclass object to a parent handle
$display(m_extend.a);
end