Qt5 中對 C++11 一些新特性的封裝

openkk 12年前發布 | 20K 次閱讀 QT

C++11 是現在的 C++ 標準的名稱,C++11 為 C++ 語言帶來很多新特性。

在 Qt5 中,提供更多 C++11 的特性支持,接下來我們將進行詳細的說明。

slots (槽) 的 Lambda 表達式

Lambda 表達式 是 C++11 中的一個新語法,允許定義匿名函數。匿名函數可用于使用小函數作為參數,而無需顯式的進行聲明。之前可以通過編寫函數指針來達到同樣的目的。

在 Qt 4.8 中已經可在一些 QtConcurrent 函數中使用 Lambda 表達式了。但在 Qt5 中甚至可以通過 new connect syntax 來將 Lambda 表達式作為 slots 來使用。

當你需要為你的 slot 編寫一個單行函數時,你可以直接在當前代碼位置編寫,這更具備可讀性:

connect (sender, &Sender::valueChanged, [=]( const QString &newValue) {
        receiver->updateValue( "senderValue" , newValue);
    });

Lambda 在 MSVC 2010, GCC 4.5, 和 clang 3.1 下也是支持的.

Unicode 文字

在 C++11 中,你可通過 u"開源中國" 來生成 UTF-16 字符串:

QString someString = QStringLiteral ( "oschina" );

請閱讀我之前發表的博文 about QStringLiteral.

常量表達式: constexpr

C++11 中全新的關鍵字 constexpr 用于注解一些 inline 函數,用于指定它們可以在編譯時進行計算。在 Qt5 中,我們引入 Q_DECL_CONSTEXPR 用來定義為 constexpr 以便讓編譯器支持。

我們同時還注解了一些 Qt 函數(例如 QFlags)允許他們直接在常量表達式中使用:

enum SomeEnum { Value1, Value2, Value3 };
Q_DECLARE_OPERATORS_FOR_FLAGS( QFlags <SomeEnum>)
// The previous line declares
// Q_DECL_CONSTEXPR QFlags<SomeValue> operator|(SomeValue,SomeValue) {...}

int someFunction( QFlags <SomeEnum> value) {
     switch (value) {
         case SomeEnum::Value1:
             return 1 ;
         case SomeEnum::Value2:
             return 2 ;
         case SomeEnum::Value1 | SomeEnum::Value3:
         // Only possible with C++11 and because QFlags operators are constexpr
         // Previously this line would call
         //        QFlags<SomeValue> operator|(SomeValue,SomeValue)
         // that would have thrown an error because only compiler constants
         // are allowed as case satement

             return 3 ;
         default :
             return 0 ;
     }
}

(在這里我還在值之前使用了 SomeEnum:: ,這在 C++11 中也是允許的,但之前是不允許的)

static_assert

C++11 可通過編譯時使用 static_assert 來幫助生成更詳細的錯誤信息,在 Qt5 中對應引入了宏 Q_STATIC_ASSERT 和 Q_STATIC_ASSERT_X ,它們可自動判斷是否可用 static_assert ,如果不支持則使用其他模板來代替。

Qt 大量的使用了一些宏定義,來避免因為編譯器不支持某些 API 時采取的相應措施。

Override 和 final

你在編碼的時候是否有過寫了錯誤的虛函數名稱,然后做了錯誤實現的情況?或者忘記了某個該死的常量?

現在你可以使用 Q_DECL_OVERRIDE 宏來聲明這是一個對虛函數進行定義的方法,來避免上述錯誤(這個類似 Java 里的 @Override 注解)。

如果編譯器支持的話,這個宏將被新的 override 屬性所替代,否則就不做任何處理。如果你使用支持 C++11 的編譯器來編譯代碼時,當你輸入錯誤的名稱時就會報編譯錯誤的信息。

class MyModel : public QStringListModel {
     //...
protected :
      Qt::ItemFlags flags ( const QModelIndex & index)  Q_DECL_OVERRIDE;
};

同樣,如果我們忘記常量名也會報錯:

mymodel.h:15: error: `Qt::ItemFlags MyModel::flags(const QModelIndex&)`
 marked override, but does not override

還有另外一個宏 Q_DECL_FINAL 用來替換新的 final 屬性,這個用來指定某個虛函數不允許被重寫。

Deleted 成員函數

新的 Q_DECL_DELETE 宏用來對 delete 屬性進行擴展,如果編譯器支持 deleted 函數的話。這個用來獲取更清楚的編譯器錯誤以避免常見的一些錯誤。

Deleted 函數用來顯式的指定不讓編譯器自動生成某些函數,例如默認的構造器或者拷貝賦值操作符等。如果使用了 Deleted 函數,那么當你在代碼中使用了相應操作就會報錯。

我們在 Q_DISABLE_COPY 宏的示例中使用過 Q_DECL_DELETE,之前是讓這些成員函數變成 private,但錯誤信息就不那么明確了。

Rvalue 引用和移動構造器

在我的文章 the Qt 4.8 article 中已經解釋過 rvalue 引用了。

因為 Qt5 中的共享類的引用計算器內部做了改變,因此現在可以 add a move constructor for many of them.

結論

MSVC 默認的支持 C++11 無需設置任何參數,但 GCC 和 Clang 需要使用 require-std=c++0x 來啟用 C++11 的支持。

默認情況下,Qt5 自身是要求用 C++11 的參數進行編譯的。

如果你使用 qmake 你可以在 .pro 項目文件中添加如下參數:

CONFIG += c++11

(在 Qt4, 這個參數寫法變成 gcc:CXXFLAGS += -std=c++0x)

現在你可以開始體驗各種 C++11 的新特性了。

英文原文,OSCHINA原創翻譯

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!