問題一:動態(tài)類型轉(zhuǎn)換和靜態(tài)類型轉(zhuǎn)換的區(qū)別金蜀?
$cast
:基本語法$case(A,B)
實(shí)際上是A=B麻裁;A表示目的端娱仔,B表示源端须肆。(downcasting)類型向下轉(zhuǎn)換
- $cast 動態(tài)類型轉(zhuǎn)換内舟,轉(zhuǎn)換失敗會報錯合敦。
- `靜態(tài)類型轉(zhuǎn)換,轉(zhuǎn)換時報不報錯
問題二:$cast是function還是task谒获?
據(jù)語境蛤肌,仿真器會自動選擇執(zhí)行task或是function,task在不需要返回值時執(zhí)行批狱,而function在需要返回值的語境下執(zhí)行裸准。將cast作為任務(wù)還是函數(shù)調(diào)用確定了無效賦值是如何處理的。
問題三:什么時候需要$cast?
我們通過下面的一個簡單的例子來進(jìn)行說明一下赔硫。
【多選題】有如下的代碼,下面$cast返回值為1的有:(BCD)
class A; endclass;
class B extends A; endclass;
class C extends B; endclass;
A a = new(…);
B b = new(…);
C c = new(…);
A炒俱、$cast(b, a)
B、a = c; $cast(b,a)
;
C爪膊、$cast(b,c)
D权悟、a = b; $cast(b, a)
解析:,
- 在解析之前推盛,希望大家能夠通讀一下綠皮書的第八章8.3.1峦阁,借用書上的一句話,將一個基類句柄賦值給一個擴(kuò)展類并不總是非法的耘成,當(dāng)基類的句柄確實(shí)指向一個派生類對象時是允許的榔昔。
$cast
子程序會檢查句柄所指向的對象類型,而不僅僅檢查句柄本身瘪菌。比如說$cast(B,A)
,會檢查句柄A指向的對象是不是句柄B指向的對象的擴(kuò)展類撒会,或者是同一類型。如果滿足的話师妙,你就可以從基類的句柄A中拷貝擴(kuò)展對象的地址給擴(kuò)展對象的句柄B了诵肛。
看到這里大家應(yīng)該會有點(diǎn)暈暈的,那我們通過實(shí)際的例子來給大家展示一下默穴,cast的實(shí)際應(yīng)用場景怔檩。
class bird;
virtual function void hungry();
$display("I am bird,I am hungry");
endfuntion
function void hungry2();
$display("I am bird,I am hungry2");
endfuntion
endclass
class parrot extends bird;
virtual function void hungry();
$display("I am parrot,I am hungry");
endfuntion
function void hungry2();
$display("I am parrot,I am hungry2");
endfuntion
endclass
program ex;
bird A;
parrot B;
initial begin
A = new();
B = new();
A.hungry();
A.hungry2();
B.hungry();
B.hungry2();
end
endprogram
運(yùn)行結(jié)果:
I am bird,I am hungry
I am bird,I am hungry2
I am parrot,I am hungry
I am parrot,I am hungry2
相信大家對這個結(jié)果夠沒有異議,那么接下來我將通過幾種場景來深入理解cast蓄诽。我們假設(shè)bird parrot的類不變珠洗,改寫program的調(diào)用。
情景一:基類 = 擴(kuò)展類
program ex;
bird A;
parrot B;
initial begin
A = new();
B = new();
A = B;
A.hungry();
A.hungry2();
B.hungry();
B.hungry2();
end
endprogram
運(yùn)行結(jié)果:
I am parrot,I am hungry
I am bird,I am hungry2
I am parrot,I am hungry
I am parrot,I am hungry2
- 基類 = 擴(kuò)展類若专;A句柄指向parrot的對象
- virtual函數(shù)的特性
- A=B,A指向B许蓖,基類指向擴(kuò)展類,在擴(kuò)展類中都能找到基類的東西,所以是OK的膊爪。
- B=A熊镣,B指向A兴使,擴(kuò)展類指向基類优烧,擴(kuò)展類的一部分東西在基類里面是找不到的夭咬。所以會報錯。
場景二:擴(kuò)展類 = 基類
program ex;
bird A;
parrot B;
initial begin
A = new();
B = new();
B = A;
A.hungry();
A.hungry2();
B.hungry();
B.hungry2();
end
endprogram
運(yùn)行結(jié)果:
Error-[SV-ICA] illegal class assignment
- 擴(kuò)展類 = 基類赃额,直接調(diào)用會有問題
- 參考場景一
場景三:cast用作task
program ex;
bird A;
parrot B;
initial begin
A = new();
B = new();
$cast(B,A);
A.hungry();
A.hungry2();
B.hungry();
B.hungry2();
end
endprogram
運(yùn)行結(jié)果:
Error-[DCF] Dynamic cast failed
-
$cast(擴(kuò)展類加派,基類)
,上述代碼$cast
沒有返回值跳芳,所以結(jié)果是做task用芍锦,根據(jù)圖【cast的task function應(yīng)用】我們可以知道,如果cast用作task應(yīng)用的時候失敗飞盆,則異常結(jié)束娄琉,直接跳出。
場景四:cast用作function
program ex;
bird A;
parrot B;
initial begin
A = new();
B = new();
if(!$cast(B,A))begin
$display("B = A; failed");
end
A.hungry();
A.hungry2();
B.hungry();
B.hungry2();
end
endprogram
運(yùn)行結(jié)果:
B = A吓歇;failed
I am bird,I am hungry
I am bird,I am hungry2
I am parrot,I am hungry
I am parrot,I am hungry2
-
if(!$cast(擴(kuò)展類孽水,基類))
,上述代碼$cast
有返回值城看,所以結(jié)果是做function用女气,根據(jù)圖【cast的task function應(yīng)用】我們可以知道,如果cast用作function應(yīng)用的時候失敗测柠,返回0主卫,繼續(xù)運(yùn)行。
場景五:cast成功轉(zhuǎn)換的應(yīng)用鹃愤,B=A,基類的句柄A指向擴(kuò)展類,擴(kuò)展類跟B句柄指向的類是同類型的完域。
program ex;
bird A;
parrot B;
initial begin
A = new();
B = new();
A = B;
if(!$cast(B,A))begin
$display("B = A; failed");
end
else begin
$display("B = A; OK !!!!");
end
A.hungry();
A.hungry2();
B.hungry();
B.hungry2();
end
endprogram
運(yùn)行結(jié)果:
B = A;OK !!!!
I am parrot,I am hungry
I am bird,I am hungry2
I am parrot,I am hungry
I am parrot,I am hungry2
-
B=A,基類的句柄A指向擴(kuò)展類软吐,擴(kuò)展類跟B句柄指向的類是同類型的。(參考書上的那句話吟税,這里通過例子深入理解一下)
A的基類句柄指向的是擴(kuò)展類的對象
B是擴(kuò)展類的句柄凹耙,指向的是擴(kuò)展類的對象
B=A,所以B可以指向A肠仪,但是要用$cast做類型轉(zhuǎn)換肖抱。
場景六:cast成功轉(zhuǎn)換的應(yīng)用,B=A,基類的句柄A指向擴(kuò)展類异旧,擴(kuò)展類是B句柄指向的類的擴(kuò)展類意述。
class dog extends parrot;
virtual function void hungry();
$display("I am dog,I am hungry");
endfuntion
function void hungry2();
$display("I am dog,I am hungry2");
endfuntion
endclass
program ex;
bird A;
parrot B;
dog C;
initial begin
A = new();
B = new();
C = new();
A = C;
if(!$cast(B,A))begin
$display("B = A; failed");
end
else begin
$display("B = A; OK !!!!");
end
A.hungry();
A.hungry2();
B.hungry();
B.hungry2();
end
endprogram
運(yùn)行結(jié)果:
B = A;OK !!!!
I am dog,I am hungry
I am bird,I am hungry2
I am dog,I am hungry
I am parrot,I am hungry2
- B=A,基類的句柄A指向擴(kuò)展類,擴(kuò)展類是B句柄指向的類的擴(kuò)展類。(參考書上的那句話荤崇,這里通過例子深入理解一下)
相信通過上述的六種場景拌屏,大家對cast應(yīng)該有了一定的了解,那么對我們最開始的那道題术荤,大家應(yīng)該都能理解了吧倚喂。
總之是一句話:在指向的時候,一定要在目的地的對象能找到我的存在瓣戚。
- 基類指向擴(kuò)展類的時候端圈,總是OK的,因?yàn)榛愒跀U(kuò)展類中總是可以找到對應(yīng)的存在子库。
- 擴(kuò)展類指向基類的時候舱权,要用$cast做類型轉(zhuǎn)換。這個時候要看基類的句柄指向的是對象是不是包含擴(kuò)展類刚照,如果是轉(zhuǎn)換就會成功刑巧。