SystemVerilog 類和物件(三)
一、類的基本概念
- 類class:是一種用來進行資料抽象的工具,將資料和對資料的操作封裝在一起,
提供建立物件的模板
,可以看做是一種資料結構。 - 物件object:是所屬類class的某一
特定實體
(也稱例項)。 - 控制程式碼handle:指向物件的指標,即
記憶體的基地址
。 - 屬性property:類class的實體object中所包含的
各種變數
variable。 - 方法method:操作變數的
任務task和函式function
。
二、物件的建立和銷燬
class word
byte nb[];
function new(int n);
nb = new[n]; //動態陣列空間開闢
endfunction
endclass
initial begin : initial_1
word wd;//宣告控制程式碼
for(int i=1;i<=4;i++) wd = new(i); //建立了4個物件
end
initial begin : initial_2
#1ps
$display("How many Bytes are allocated for word instance?")
end
若wd = new(1)所需開闢的空間為1B,那麼執行完開闢空間:
wd執行完,控制程式碼指向第四個物件,4B。由於initial中是靜態變數,即使initial執行完了,那麼變數還在。
三、物件控制程式碼的深拷貝 與 淺拷貝
1)、 淺拷貝:只拷貝物件中的資料變數,淺拷貝前後的資料變數使用不同的記憶體空間;而對於物件中的**資料操作(任務和函式)**和其中定義的其它類的控制程式碼,採取類似“引用操作”的方式,淺拷貝前後共用同一記憶體空間。
BusTran bt0, bt1; //宣告兩個控制程式碼
b1 = new(); //b1建立物件
b2 = new b1; //b2建立物件,同時對b1進行淺拷貝
2)、 深拷貝:對於物件中的所有成員統一分配新的記憶體空間,區別於淺拷貝。
BusTran bt0, bt1; //宣告兩個控制程式碼
b1 = new(); //b1建立物件
b2 = new(); //b2建立物件
b2.copy(b1); //深拷貝,自定義copy函式
四、類的特性
class clock
local bit is_summer = 0;
local int nclock = 6;
function int get_clock();
if(!is_summer) return this.nclock;
else return this.nclock+1;
endfunction
function bit set_summer(bit s);
this.is_summer = s;
endfunction
endclass
clock ck;
initial begin
ck = new();
$display("now tome is %0d", ck.get_clock());
ck.set_summer(1);
$display("noe time is %0d", ck.nclock);
end
第一個列印為6;第二個編譯出錯。外部控制程式碼ck不能訪問nclock變數(加了限定local)。但可以訪問沒加限制的function。
4.1.封裝
4.2.繼承
子類繼承了父類所有的成員方法和屬性,並且可以擁有自己特性。通過關鍵字extends實現繼承解決了程式碼的重用問題。
子類既包含繼承父類的成員方法和屬性,也有自己獨特的個性方法(青出於藍而勝於藍),所以如果想要將一個指向父類的指標轉化為指向子類的指標,無法直接轉換,(父親大人,時代變了!)必須通過$cast()
,在system veilog中被稱為向下型別轉換
(downcasting)。
- 向上型別轉換:
transaction_class tr = new(); //父類
subtransaction_class sc = new(); //子類
tr = sc; //子類(右)指向父類(左),這是正確的可以直接轉換
- $cast向下型別轉換
transaction_class tr;//父類
subtransaction_class sc; //子類
sc = new();
tr = sc; //控制程式碼型別轉化為同一型別,父控制程式碼型別轉化為子控制程式碼型別
$cast(sc,tr); // 通過cast方式可以實現,可以看到tr的控制程式碼型別雖然是父類,但其指的物件型別是子類
子類繼承父類時新增加一個函式,該函式與父類中的某函式同名,呼叫時會呼叫新增的函式,而不是繼承下來的函式。
- 如果父類與子類的函式同名,但是引數不同,此時不論有無關鍵字virtual,父類的函式都將被隱藏。
- 如果父類與子類的函式同名,引數也相同,但是基類函式無關鍵字virtual,父類的函式都將被隱藏。(如果父類函式有virtual,則會形成多型)
對於子類類新增同名函式成員的訪問:“物件名.成員名”;
對於父類中同名函式成員的訪問:“(子類)物件名.基類名::成員名”
4.3.多型
呼叫同一個函式,實現不同的行為就是多型。但要滿足兩點要求:
- 必須通過父類的指標或者引用呼叫虛擬函式
被呼叫的函式必須是虛擬函式,且子類必須對基類的虛擬函式進行重寫
。
虛擬函式virtual function
被virtual修飾的類成員函式稱為虛擬函式。虛擬函式是動態繫結的,如果子類需要修改父類的行為(即重寫與基類函式同名的函式),就應該在父類中將相應的函式宣告為虛擬函式。使用虛擬函式應當注意:
- 父類中某一成員函式宣告為virtual虛擬函式後,子類中的同名函式(同名、同參、同型別)自動生成虛擬函式。
- 子類的同名虛擬函式會
重寫或覆蓋
原來父類中的同名虛擬函式.。
虛類virtual class
虛類通過關鍵字virtual宣告,不能被例化(不能建立物件),但可以通過派生,生成有用的子類,也可宣告一個虛類的指標,通過抽象類的指標指向不同的子類物件。進而訪問子類物件的虛擬函式,實現多型性。
正常情況下,父類是不可以訪問子類中方法的,但是通過虛父類可以實現。
module OOP_EXTENDS();
class BusTran;
bit [31:0] addr,crc,data[7];
virtual function bit[31:0] calc_crc; //虛方法目的——實現多型
crc=addr^data.xor; //異或:奇數個1異或,結果為1;偶數個1異或,結果為0
calc_crc=crc; //返回值
endfunction
function void dsp_addr(input string handle);
$display("*****%s.ADDR = %0h",handle,addr);
endfunction
function void dsp_crc(input string handle);
$display("*****BusTran %s.crc = %h",handle,crc);
endfunction
endclass
class BadBusTran extends BusTran; //繼承
bit bad_crc;
virtual function bit[31:0] calc_crc(); //虛方法目的——實現多型; 派生類中的同名函式的virtual可以省略
super.calc_crc(); //通過關鍵字super,實現子類對父類成員的呼叫
if(bad_crc) crc = ~crc;
calc_crc = crc;
endfunction
endclass
BusTrans bt0; //宣告父類控制程式碼
BadBusTran bbt0; //宣告父類控制程式碼
initial begin
bt0 = new;
$display("*****handle bt0 is : %0h",bt0);
bbt0 = new;
$display("*****handle bbt0 is : %0h",bbt0);
bt0.addr = 32'hFFFF_FFFF;
bt0.dsp_addr("bt0");
bbt0.addr = 32'h1111_1111;
bt0.dsp_addr("bbt0");
foreach(bt0.data[i]) begin
bt0.data[i] = 32'h0000_FFFF;
end
bt0.calc_crc;
bt0.dsp_crc("bt0");
foreach(bbt0.data[i]) begin
bbt0.data[i] = 32'hFFFF_FFFF;
end
bbt0.calc_crc; //此時未設定bad_crc,二值變數預設初始值為0
bbt0.dsp_crc("bbt0");
bbt0.bad_crc = 1;
$display("*****After bad crc set to 1");
bbt0.calc_crc;
bbt0.dsp_crc("bbt0");
end
//Polymorphism——多型
function bit[31:0] crc(BusTran bt); //多型——控制程式碼傳遞過程中,會根據控制程式碼自動識別所屬類
crc = bt.calc_crc();
endfunction
bit [31:0] crc_value;
initial begin
#10;
crc_value = crc(bt0);
$display("*****crc from bt0 = %0h",crc_value);
crc_value = crc(bbt0);
$display("*****crc from bt0 = %0h",crc_value);
end
endmodule
包的使用
參考:
相關文章
- Kotlin教程(三)類、物件和介面Kotlin物件
- 類和物件物件
- Java 物件和類Java物件
- Scala 類和物件物件
- 【Kotlin】類和物件Kotlin物件
- 類和物件(中)物件
- Java 類和物件Java物件
- 類和物件案例物件
- Java物件和類Java物件
- 實驗三 類和物件 基礎程式設計2物件程式設計
- 實驗三 類和物件_基礎程式設計2物件程式設計
- c++類和物件C++物件
- C++ 類和物件C++物件
- 6.類和物件物件
- 類圖和物件圖物件
- 認識類和物件物件
- 第10章 物件和類——物件和類(六) 抽象資料型別物件抽象資料型別
- C++類和物件是什麼?C++類和物件詳解C++物件
- 前端進階-類和物件前端物件
- 3.java類和物件Java物件
- java裡的物件和類Java物件
- Java基礎| 類和物件Java物件
- 4、類和物件—封裝物件封裝
- 初識Java類和物件Java物件
- cpp中的類和物件物件
- Java類和物件 小白版Java物件
- 實驗2 類和物件物件
- 實驗3 類和物件物件
- Java 學習:物件和類Java物件
- 實體類定義陣列物件,和物件陣列物件
- 10.17 day14 類和物件物件
- 物件導向的基本理論1:類和物件物件
- PHP 手冊 (類與物件) 學習筆記三:類常量PHP物件筆記
- 類和物件部分知識總結物件
- PHP 底層原理之類和物件PHP物件
- python中類和物件的__dict__Python物件
- Python基礎(二十):物件導向“類”第三課——類成員Python物件
- 物件導向 -- 類的載入順序 類和物件的名稱空間物件