一、前言 在IC前端設計/驗證領域,只會HDL遠遠不夠。目前大多數項目使用已開發好的系統架構和IP Core,因此設計部分的工作量慢慢向系統集成和驗證方向轉移。而在集成和驗證過程中,往往以各種腳本和麵向對象的高級語言為主要工具。SystemVerilog已成為主流驗證語言,相當於VerilogHDL ...
一、前言
在IC前端設計/驗證領域,只會HDL遠遠不夠。目前大多數項目使用已開發好的系統架構和IP Core,因此設計部分的工作量慢慢向系統集成和驗證方向轉移。而在集成和驗證過程中,往往以各種腳本和麵向對象的高級語言為主要工具。SystemVerilog已成為主流驗證語言,相當於VerilogHDL與C++的結合體。故掌握C++基礎是十分必要的。
二、類封裝示例及解讀
本文以《C++ Primer Plus》書中的一個簡單的代碼示例,講講自己對類封裝的理解。出於練習、總結和記錄的目的。OOP設計思想中:萬物皆為某一類中的一個對象,類即為一群具有共性對象的抽象表示。每個類包含了數據成員和方法,成員是類包含的特性,而方法表示這一類的對象能完成哪些事情。以下示例描述的是股票這一類別。股票肯定包含股票數量和每股的價錢了。至於方法最起碼可以買、賣,變動價格吧。
一般將類聲明、方法定義分別放置在class_name.h和class_name.cpp文件中。這樣的做法正符合了“封裝”、“細節隱藏”的思想,讓應用程式無需關註實現細節,這一點與C語言一致。先來看看class_name.h文件中類聲明。
1 #ifndef STOCK00_H_ 2 #define STOCK00_H_ 3 4 #include <string> 5 6 class Stock 7 { 8 private: 9 std::string m_company; 10 long m_shares; 11 double m_share_val; 12 double m_total_val; 13 void set_tot() {m_total_val = m_shares * m_share_val;}//內聯函數 14 public: 15 //two constructors 16 Stock();//default constructor 17 Stock(const std::string &co,long n = 0,double pr = 0.0); 18 //destructor 19 ~Stock(); 20 void acquire(const std::string &co,long n,double pr); 21 void buy(long num,double price); 22 void sell(long num,double price); 23 void update(double price); 24 void show() const;//promises not to change invoking object 25 const Stock &topval(const Stock &s) const; 26 }; 27 28 #endifstock00.h
Stock類聲明中包含了兩個最常用的訪問控制關鍵字pritive和public。class與C語言中結構體類似,只不過結構體數據成員均為public。pritive部分只能通過共有成員函數訪問。m_company m_shares m_share_val和m_total_val分別代表公司名稱、股票數量、股票單價以及總價。其中set_tot()為定義在類聲明中的成員函數,稱之為內聯函數。該函數只能被公有成員函數調用。
公有成員函數acquaire buy sell update show和topval依次完成公司首次持股、買股票、賣股票、股價變動、顯示某公司股票信息以及尋找兩公司股票總價最高者的操作。有兩類比較特殊的函數:構造函數Stock()和析構函數~Stock()。前者負責類對象的初始化,析構函數則是逆向操作,用於對象銷毀時的清理工作,如釋放動態分配記憶體等。
類方法定義:
#include <iostream> #include "stock00.h" Stock::Stock() { std::cout << "Default constructor called.\n"; m_company = "no name"; m_shares = 0; m_share_val = 0.0; m_total_val = 0.0; } Stock::Stock(const std::string &co,long n,double pr) { std::cout << "Constructor using " << co << " called\n"; m_company = co; if(n<0) { std::cout <<"Number of shares can't be negative;" << m_company << "shares set to 0.\n"; m_shares = 0; } else m_shares = n; m_share_val = pr; set_tot(); } Stock::~Stock() { std::cout << "Bye, " << m_company << "!\n"; } void Stock::acquire(const std::string &co,long n,double pr) { m_company = co; if(n<0) { std::cout << "Number of shares can't be negative; " << m_company << "shares set to 0.\n"; m_shares = 0; } else m_shares = n; m_share_val = pr; set_tot(); } void Stock::buy(long num, double price) { if(num<0) { std::cout << "Number of shares purchased can't be negative." << "Transcation is aborted.\n"; } else { m_shares += num; m_share_val = price; set_tot(); } } void Stock::sell(long num,double price) { using std::cout; if(num < 0) { cout << "Number of shares sold can't be negative. " << "Transcation is aborted.\n"; } else if(num > m_shares) { cout <<"You can't sell more than you have! " << "Transcation is aborted.\n"; } else { m_shares -=num; m_share_val = price; set_tot(); } } void Stock::update(double price) { m_share_val = price; set_tot(); } void Stock::show() const { std::cout << "Company: " << m_company << " Shares: " << m_shares << '\n' << "share Price:$" << m_share_val << " total worth:$" << m_total_val<< std::endl; } //選擇總價最高的股票,返回該股票 const Stock & Stock::topval(const Stock &s) const { if(s.m_total_val > m_total_val) return s; else return *this; }stock00.cpp
為了清晰看到構造和析構函數的隱式調用,使用cout列印相關信息。可以看到涉及到股價變動的操作時,均會調用set_tot()函數更新總股價。show()和topval()兩個函數後有“const”標識符,表明兩者是const成員函數。這種方式可以顯示告知編譯器:該函數不會改變傳輸實參。否則創建const類對象,且該對象調用show()函數時會報錯。topval函數中返回的this指針會指向用來調用成員函數對象。
三、應用程式及結果分析
應用程式代碼如下:
1 #include <iostream> 2 #include "stock00.h" 3 4 const int STKS = 4; 5 int main() 6 { 7 Stock stocks[STKS] = {//create object array of Stock class 8 Stock("NanoSmart",12,20.0), 9 Stock("Boffo Objects",200,2.0), 10 Stock("Monolithic Obelisks",130,3.25), 11 Stock("Fleep Enterprises",60,6.5) 12 }; 13 14 std::cout << "Stock holdings:\n"; 15 int st; 16 for (st=0;st<STKS;st++) 17 { 18 stocks[st].show();//show informations 19 } 20 21 //set top pointer to the first element 22 const Stock *top = &stocks[0]; 23 for(st=1;st<STKS;st++) 24 { 25 top = &top ->topval(stocks[st]); 26 } 27 //now top points to the most valuable holding 28 std::cout <<"\nMost valuable holding:\n"; 29 top->show(); 30 return 0; 31 }usestock0.cpp
親切的main函數終於現身了!這裡首先創建了一個Stock類的對象組成的數據stocks。其每個元素使用了顯示方式調用構造函數。作為Stock類的對象stocks[0]-stock[3]自然可以調用類方法。之後stocks[st].show()處列印每隔公司的股票信息。接著找出總股價最高的公司,並顯示信息信息。由於topval()函數僅能兩兩比較,故利用for迴圈找出最大者。精華都在這一句:top = &top ->topval(stocks[st]); 意思是:Stock類的指針top指向的Stock類對象與實參對象中總股價最大者的地址更新top。(確實有點繞)
最後看看列印結果:
列印結果表明,topval()函數成功索引到總股價最高的公司:Monolithic Obelisks。top->show()函數列印出其詳細信息。最後列印了類對象數組元素對應的bye信息,證明析構函數被隱式調用。後續會在軟體_腳本專欄中繼續講述C++基礎示例、Linux Shell腳本等相關內容。