SystemVerilog是否支持向下转换(将基础对象转换为派生对象)?如果是这样,怎么样?
以下向下转播示例不起作用:
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
修改并重新运行EDA Playground上的示例:http://www.edaplayground.com/s/4/581
答案 0 :(得分:9)
是的,你可以垂头丧气。您的示例是正确的语法,它实际上是编译。但是,由于转换失败,您将收到运行时错误。
您示例中的强制转换失败,因为如果基础对象的句柄实际引用派生类型的对象,则只能成功转发。您可以将$cast
作为函数调用,它将返回一个布尔值,指示转换是否成功。
以下是一个例子:
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
答案 1 :(得分:4)
IEEE Std 1800-2012§8.16“施法”声明:
将子类类型的表达式分配给继承树(表达式类型的超类或祖先)中更高类类型的变量始终是合法的。将超类类型的变量直接分配给其子类类型之一的变量是非法的。但是,
$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
以下是一些工作示例:http://www.edaplayground.com/s/6/587