前面我們?cè)诮榻B QString 的最后部分曾經(jīng)提到了 QByteArray 這個(gè)類(lèi)?,F(xiàn)在我們就首先對(duì)這個(gè)類(lèi)進(jìn)行介紹。
QByteArray 具有類(lèi)似與 QString 的 API。它也有相應(yīng)的函數(shù),比如 left(), right(), mid()等。這些函數(shù)不僅名字和 QString 一樣,而且也具有幾乎相同的功能。QByteArray 可以存儲(chǔ)原生的二進(jìn)制數(shù)據(jù)和8位編碼的文本數(shù)據(jù)。這句話怎么理解呢?我們知道,計(jì)算機(jī)內(nèi)部所有的數(shù)據(jù)都是以0和1的形式存儲(chǔ)的。這種形式就是二進(jìn)制。比如一串0、1代碼:1000,計(jì)算機(jī)并不知道它代表的是什么,這需要由上下文決定:它可以是整數(shù)8,也可以是一個(gè) ARGB 的顏色(準(zhǔn)確的說(shuō),整數(shù)8的編碼并不是這么簡(jiǎn)單,但我們姑且這個(gè)理解吧)。對(duì)于文件,即便是一個(gè)文本文件,讀出時(shí)也可以按照二進(jìn)制的形式讀出,這就是二進(jìn)制格式。如果把這些二進(jìn)制的0、1串按照編碼解釋成一個(gè)個(gè)字符,就是文本形式了。因此,QByteArray 實(shí)際上是原生的二進(jìn)制,但是也可以當(dāng)作是文本,因此擁有文本的一些操作。但是,我們還是建議使用 QString 表示文本,重要的原因是,QString 支持 Unicode。
為了方便期間,QByteArray 自動(dòng)的保證“最后一個(gè)字節(jié)之后的那個(gè)位”是'\0'。這就使得 QByteArray可以很容易的轉(zhuǎn)換成 const char *,也就是上一章節(jié)中我們提到的那兩個(gè)函數(shù)。同樣,作為原生二進(jìn)制存儲(chǔ),QByteArray 中間也可以存儲(chǔ)'\0',而不必須是'\0'在最后一位。
在有些情況下,我們希望把數(shù)據(jù)存儲(chǔ)在一個(gè)變量中。例如,我有一個(gè)數(shù)組,既希望存整數(shù),又希望存浮點(diǎn)數(shù),還希望存 string。對(duì)于 Java 來(lái)說(shuō),很簡(jiǎn)單,只要把這個(gè)數(shù)組聲明成 Object[]類(lèi)型的。這是什么意思呢?實(shí)際上,這里用到的是繼承。在 Java 中,int 和 float 雖然是原生數(shù)據(jù)類(lèi)型,但是它們都有分別對(duì)應(yīng)一個(gè)包裝類(lèi) Integer 和 Float。所有這些 Integer、Float 和 String 都是繼承于Object,也就是說(shuō),Integer、Float 和 String 都是一個(gè)(也就是 is-a 的關(guān)系)Object,這樣,Object 的數(shù)組就可以存儲(chǔ)不同的類(lèi)型。但是,C++中沒(méi)有這樣一個(gè) Object 類(lèi),原因在于,Java 是單根的,而 C++不是。在 Java 中,所有類(lèi)都可以上溯到 Object 類(lèi),但是 C++中沒(méi)有這么一個(gè)根。那么,怎么實(shí)現(xiàn)這么的操作呢?一種辦法是,我們都存成 string 類(lèi),比如 int i=10,我就存"10"字符串。簡(jiǎn)單的數(shù)據(jù)類(lèi)型固然可以,可復(fù)雜一些的呢?比如一個(gè)顏色?難道要把 ARGB 所有的值都轉(zhuǎn)化成string?這種做法很復(fù)雜,而且失去了 C++的類(lèi)型檢查等好處。于是我們想另外的辦法:創(chuàng)建一個(gè)Object 類(lèi),這是一個(gè)“很大很大的”類(lèi),里面存儲(chǔ)了幾乎所有的數(shù)據(jù)類(lèi)型,比如下面的代碼:
class Object
{
public:
int intValue;
float floatValue;
string stringValue;
};
這個(gè)類(lèi)怎么樣?它就足以存儲(chǔ) int、float 和 string 了。嗯,這就是我們的思路,也是 Qt 的思路。在 Qt 中,這樣的類(lèi)就是 QVariant。
QVariant 可以保存很多 Qt 的數(shù)據(jù)類(lèi)型,包括 QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize 和 QString,并且還有 C++基本類(lèi)型,如 int、float 等。QVariant 還能保存很多集合類(lèi)型,如 QMap<QString, QVariant>, QStringList 和 QList
QMap<QString, QVariant> pearMap;
pearMap["Standard"] = 1.95;
pearMap["Organic"] = 2.25;
QMap<QString, QVariant> fruitMap;
fruitMap["Orange"] = 2.10;
fruitMap["Pineapple"] = 3.85;
fruitMap["Pear"] = pearMap;
QVariant 被用于構(gòu)建 Qt Meta-Object,因此是 QtCore 的一部分。當(dāng)然,我們也可以在 GUI 模塊中使用,例如
QIcon icon("open.png");
QVariant variant = icon;
// other function
QIcon icon = variant.value<QIcon>();
我們使用了 value
如果你覺(jué)得 QVariant 提供的存儲(chǔ)數(shù)據(jù)類(lèi)型太少,也可以自定義 QVariant 的存儲(chǔ)類(lèi)型。被 QVariant 存儲(chǔ)的數(shù)據(jù)類(lèi)型需要有一個(gè)默認(rèn)的構(gòu)造函數(shù)和一個(gè)拷貝構(gòu)造函數(shù)。為了實(shí)現(xiàn)這個(gè)功能,首先必須使用 Q_DECLARE_METATYPE()宏。通常會(huì)將這個(gè)宏放在類(lèi)的聲明所在頭文件的下面:
Q_DECLARE_METATYPE(BusinessCard)
然后我們就可以使用:
BusinessCard businessCard;
QVariant variant = QVariant::fromValue(businessCard);
// ...
if (variant.canConvert<BusinessCard>()) {
BusinessCard card = variant.value<BusinessCard>();
// ...
}
由于 VC 6的編譯器限制,這些模板函數(shù)不能使用,如果你使用這個(gè)編譯器,需要使用qVariantFromValue(), qVariantValue
qRegisterMetaTypeStreamOperators<BusinessCard>("BusinessCard");
本文出自 “豆子空間” 博客,請(qǐng)務(wù)必保留此出處 http://devbean.blog.51cto.com/448512/193918