QByteArray和QVariant

來源:互聯網
上載者:User

前面我們在介紹QString的最後部分曾經提到了QByteArray這個類。現在我們就首先對這個類進行介紹。

QByteArray具有類似與QString的API。它也有相應的函數,比如left(), right(), mid()等。這些函數不僅名字和QString一樣,而且也具有幾乎相同的功能。QByteArray可以儲存原生的位元據和8位編碼的文本資料。這句話怎麼理解呢?我們知道,電腦內部所有的資料都是以0和1的形式儲存的。這種形式就是二進位。比如一串0、1代碼:1000,電腦並不知道它代表的是什麼,這需要由上下文決定:它可以是整數8,也可以是一個ARGB的顏色(準確的說,整數8的編碼並不是這麼簡單,但我們姑且這個理解吧)。對於檔案,即便是一個文字檔,讀出時也可以按照二進位的形式讀出,這就是二進位格式。如果把這些二進位的0、1串按照編碼解釋成一個個字元,就是文本形式了。因此,QByteArray實際上是原生的二進位,但是也可以當作是文本,因此擁有文本的一些操作。但是,我們還是建議使用QString表示文本,重要的原因是,QString支援Unicode。

為了方便期間,QByteArray自動的保證“最後一個位元組之後的那個位”是'/0'。這就使得QByteArray可以很容易的轉換成const char *,也就是上一章節中我們提到的那兩個函數。同樣,作為原生二進位儲存,QByteArray中間也可以儲存'/0',而不必須是'/0'在最後一位。

在有些情況下,我們希望把資料存放區在一個變數中。例如,我有一個數組,既希望存整數,又希望存浮點數,還希望存string。對於Java來說,很簡單,只要把這個數組聲明成Object[]類型的。這是什麼意思呢?實際上,這裡用到的是繼承。在Java中,int和float雖然是原生資料類型,但是它們都有分別對應一個封裝類Integer和Float。所有這些Integer、Float和String都是繼承於Object,也就是說,Integer、Float和String都是一個(也就是is-a的關係)Object,這樣,Object的數組就可以儲存不同的類型。但是,C++中沒有這樣一個Object類,原因在於,Java是單根的,而C++不是。在Java中,所有類都可以上溯到Object類,但是C++中沒有這麼一個根。那麼,怎麼實現這麼的操作呢?一種辦法是,我們都存成string類,比如int i=10,我就存"10"字串。簡單的資料類型固然可以,可複雜一些的呢?比如一個顏色?難道要把ARGB所有的值都轉化成string?這種做法很複雜,而且失去了C++的類型檢查等好處。於是我們想另外的辦法:建立一個Object類,這是一個“很大很大的”類,裡面儲存了幾乎所有的資料類型,比如下面的代碼:

 
  1. class Object  
  2. {  
  3. public:  
  4.     int intValue;  
  5.     float floatValue;  
  6.     string stringValue;  
  7. }; 

這個類怎麼樣?它就足以儲存int、float和string了。嗯,這就是我們的思路,也是Qt的思路。在Qt中,這樣的類就是QVariant。

QVariant可以儲存很多Qt的資料類型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,並且還有C++基本類型,如int、float等。QVariant還能儲存很多集合類型,如QMap<QString, QVariant>, QStringList和QList<QVariant>。item view classes,資料庫模組和QSettings都大量使用了QVariant類,,以方便我們讀寫資料。

QVariant也可以進行嵌套儲存,例如

 
  1. QMap<QString, QVariant> pearMap;  
  2. pearMap["Standard"] = 1.95;  
  3. pearMap["Organic"] = 2.25;  
  4.  
  5. QMap<QString, QVariant> fruitMap;  
  6. fruitMap["Orange"] = 2.10;  
  7. fruitMap["Pineapple"] = 3.85;  
  8. fruitMap["Pear"] = pearMap; 

QVariant被用於構建Qt Meta-Object,因此是QtCore的一部分。當然,我們也可以在GUI模組中使用,例如

 
  1. QIcon icon("open.png");  
  2. QVariant variant = icon;  
  3. // other function  
  4. QIcon icon = variant.value<QIcon>(); 

我們使用了value<T>()模版函數,擷取儲存在QVariant中的資料。這種函數在非GUI資料中同樣適用,但是,在非GUI模組中,我們通常使用toInt()這樣的一系列to...()函數,如toString()等。

如果你覺得QVariant提供的儲存資料類型太少,也可以自訂QVariant的儲存類型。被QVariant儲存的資料類型需要有一個預設的建構函式和一個拷貝建構函式。為了實現這個功能,首先必須使用Q_DECLARE_METATYPE()宏。通常會將這個宏放在類的聲明所在標頭檔的下面:

 
  1. Q_DECLARE_METATYPE(BusinessCard) 

然後我們就可以使用:

 
  1. BusinessCard businessCard;  
  2. QVariant variant = QVariant::fromValue(businessCard);  
  3. // ...  
  4. if (variant.canConvert<BusinessCard>()) {  
  5.     BusinessCard card = variant.value<BusinessCard>();  
  6.     // ...  

由於VC 6的編譯器限制,這些模板函數不能使用,如果你使用這個編譯器,需要使用qVariantFromValue(), qVariantValue<T>()和qVariantCanConvert<T>()這三個宏。

如果自訂資料類型重寫了<<和>>運算子,那麼就可以直接在QDataStream中使用。不過首先需要使用qRegisterMetaTypeStreamOperators<T>().宏進行註冊。這就能夠讓QSettings使用操作符對資料進行操作,例如

 
  1. qRegisterMetaTypeStreamOperators<BusinessCard>("BusinessCard"); 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.