2013-12-12 11 views
5

Czy SystemVerilog obsługuje downcasting (rzutowanie obiektu podstawowego na obiekt pochodny)? Jeśli tak to jak?Czy SystemVerilog obsługuje downcasting?

Poniższy przygnębiony przykład nie działa:

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 

Modyfikuj i ponownie przykład na EDA Playground: http://www.edaplayground.com/s/4/581

Odpowiedz

7

Tak, można przygnębiony. Twój przykład to poprawna składnia i faktycznie się kompiluje. Jednak pojawia się błąd środowiska wykonawczego, ponieważ odtwarzanie nie powiedzie się.

Przykład "Rzucanie w siebie" kończy się niepowodzeniem, ponieważ można pomyślnie zakończyć proces downcastu tylko wtedy, gdy uchwyt obiektu bazowego jest faktycznym odniesieniem do obiektu typu pochodnego. Możesz wywołać funkcję $cast jako funkcję i zwróci ona wartość logiczną wskazującą, czy rzutowanie zakończyło się powodzeniem, czy nie.

Oto przykład:

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 

Wyjścia:

# Found a dog! 
# woof 

Zobacz http://www.edaplayground.com/s/474/586

+0

tak więc spuszczone działa tylko wtedy, gdy obiekt źródłowy został najpierw upcast. –

+1

Tak, w przeważającej części. Nie musi to być wynikiem jawnego upcastu, ale powinieneś mieć odniesienie typu bazowego wskazujące na obiekt typu pochodnego. – dwikle

3

IEEE Std 1800-2012 § 8,16 "Casting" stwierdza:

It zawsze dopuszczalne jest przypisywanie wyrażenia typu podklasy do zmiennej typu klasy wyższej w drzewie dziedziczenia (nadklasa lub element nadrzędny typu wyrażenia). Niedozwolone jest bezpośrednie przypisywanie zmiennej typu nadklasy do zmiennej jednego z jej typów podklas. Jednakże, można użyć $cast do przyporządkowania uchwytu klasy nadklasy do zmiennej typu podklasy, pod warunkiem, że uchwyt nadklasy odnosi się do obiektu, który jest przypisaniem kompatybilnym z zmienną podklasy.

Następujące zaległości nie powiodły się, ponieważ obiekt nadklasy nie został odczytany jako klasa potomna.

m_base = new(); 
$cast(m_extend, m_base); // destination type != source object type 

Aby rzucić poprawnie przedmiot uchwyt źródłowego muszą być zgodne z typetypes docelowe muszą być porównywalne:

m_extend = new(); 
m_base = m_extend; 
$cast(m_extend, m_base); // destination type == source object type 

rzutowanie w dół może pracować przez poziomy dziedziczenia. Poniższy przykład pokazuje uchwyt klasa bazowa wskazując obiekt wnuka być lanego do klasy rozszerzenia (klasa dominująca obiektu wnuka):

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 

Oto niektóre z przykładów pracy: http://www.edaplayground.com/s/6/587