做網(wǎng)站媒體內(nèi)蒙古seo優(yōu)化
概述
????????C++ 11中引入了許多簡(jiǎn)化編程工作的語(yǔ)法上的新特性,我們暫且美其名曰:“語(yǔ)法甜點(diǎn)”。書(shū)接上篇,我們繼續(xù)介紹C++ 11中的這些“語(yǔ)法甜點(diǎn)”,也是第二篇關(guān)于“語(yǔ)法甜點(diǎn)”的文章。
語(yǔ)法甜點(diǎn)6:模板右邊雙括號(hào)
????????在C++ 03中,vector<vector<int>> vctTemp是一個(gè)非法的表達(dá)式,編譯器會(huì)認(rèn)為右邊的>>是一個(gè)移位操作符,因此必須修改為:vector<vector<int> > vctTemp,即在右邊的兩個(gè)>中間添加一個(gè)空格。在C++ 11中,這將不再是一個(gè)問(wèn)題,編譯器將能夠識(shí)別出右邊的雙括號(hào)是兩個(gè)模板參數(shù)列表的結(jié)尾。
語(yǔ)法甜點(diǎn)7:static_assert
????????靜態(tài)斷言static_assert由一個(gè)常量表達(dá)式和一個(gè)字符串構(gòu)成。在編譯期間,將計(jì)算常量表達(dá)式的值;如果為false,字符串將作為錯(cuò)誤信息輸出。
#include <iostream>
using namespace std;int main()
{char cNumber = 66;static_assert(sizeof(cNumber) == 4, "not an interger");return 0;
}
語(yǔ)法甜點(diǎn)8:初始化列表
????????在引入C++ 11之前,只有數(shù)組能使用初始化列表。在C++ 11中,vector、list等各種容器以及string都可以使用初始化列表了。初始化列表對(duì)應(yīng)的類(lèi)為initializer_list,vector、list等各種容器以及string之所以可以使用初始化列表,是因?yàn)樗鼈冎剌d了參數(shù)類(lèi)型為initializer_list的構(gòu)造函數(shù)(稱(chēng)為初始化列表構(gòu)造函數(shù))和賦值函數(shù)(稱(chēng)為初始化列表賦值函數(shù))。
#include <iostream>
#include <vector>
#include <map>
using namespace std;void Print(const initializer_list<int> &ilData)
{for (auto a : ilData){cout << a << endl;}
}int main()
{vector<int> vctNum = {1, 2, 3, 4, 5};map<string, string> mapID2Name = {{"92001", "Tom"}, {"92002", "Mike"}};string strText{"Hello CSDN"};Print({});Print({1, 2});Print({1, 2, 3, 4, 5});return 0;
}
語(yǔ)法甜點(diǎn)9:默認(rèn)或禁用函數(shù)
????????當(dāng)我們定義了自己的帶參數(shù)的構(gòu)造函數(shù)時(shí),編譯器將不再生成默認(rèn)的構(gòu)造函數(shù),如果此時(shí)想使用默認(rèn)的構(gòu)造函數(shù),則必須顯式地聲明并定義不帶參數(shù)的構(gòu)造函數(shù)。在C++ 11中,我們可以使用default關(guān)鍵字來(lái)表明我們希望使用默認(rèn)的構(gòu)造函數(shù)。
????????類(lèi)似的,當(dāng)我們不想外部使用編譯器自動(dòng)生成的構(gòu)造函數(shù)或賦值函數(shù)時(shí),我們一般需要將其聲明成protected或private的。在C++ 11中,我們可以使用delete關(guān)鍵字來(lái)表明我們不希望編譯器生成默認(rèn)的構(gòu)造函數(shù)或賦值函數(shù)。
class CPerson
{
public:CPerson() = default;CPerson(const CPerson &person) = delete;
};
????????另外,=delete的聲明(同時(shí)也是定義)也能適用于非自帶函數(shù),以禁止成員函數(shù)以特定的形參調(diào)用。
class CNoDouble
{void f(int i);void f(double) = delete;
};
????????若嘗試以double的形參調(diào)用f(),將會(huì)引發(fā)編譯錯(cuò)誤,編譯器不會(huì)自動(dòng)將double形參轉(zhuǎn)換為int再調(diào)用f()。 若要徹底禁止以非int的形參調(diào)用f(),可以將=delete與模板相結(jié)合。
class COnlyInt
{void f(int i);template<class T> void f(T) = delete;
};
語(yǔ)法甜點(diǎn)10:繼承的構(gòu)造函數(shù)
????????當(dāng)一個(gè)派生類(lèi)的某個(gè)函數(shù)隱藏了基類(lèi)中的某個(gè)同名函數(shù)時(shí),如果我們想在派生類(lèi)中導(dǎo)出基類(lèi)中的這個(gè)同名函數(shù),可以通過(guò)using Base::Func的方式將基類(lèi)中的這個(gè)同名函數(shù)引入到派生類(lèi)的作用域內(nèi)。但該方法只對(duì)普通成員函數(shù)有效,不能用于構(gòu)造函數(shù)。
????????在C++ 11中,如果派生類(lèi)認(rèn)為基類(lèi)的構(gòu)造函數(shù)已經(jīng)足夠,則也可以使用using Base::Base的方式將基類(lèi)的構(gòu)造函數(shù)引入到派生類(lèi)的作用域內(nèi)。注意:此時(shí)派生類(lèi)中的成員變量并沒(méi)有進(jìn)行初始化,所以應(yīng)當(dāng)對(duì)這些成員變量進(jìn)行就地初始化。
#include <iostream>
#include <string>
using namespace std;class CBase
{
public:CBase(int nValue) : m_nValue(nValue){cout << "Base constructor with int" << endl;}CBase(double dValue) : m_nValue((int)(dValue * 10)){cout << "Base constructor with double" << endl;}private:int m_nValue;
};class CDerived : public CBase
{
public:// 使用 using 關(guān)鍵字引入基類(lèi)的所有構(gòu)造函數(shù)到派生類(lèi)中using CBase::CBase;// 如果需要添加額外的成員變量或自定義構(gòu)造函數(shù),可以繼續(xù)定義CDerived(const string &strText) : CBase((int)strText.size()){cout << "Derived constructor with string" << endl;}
};int main()
{// 調(diào)用 CBase(int) 構(gòu)造函數(shù)CDerived d1(5);// 調(diào)用 CBase(double) 構(gòu)造函數(shù)CDerived d2(3.14);// 調(diào)用 CDerived(const string &) 構(gòu)造函數(shù)CDerived d3("Hello CSDN");return 0;
}
????????在上面的示例代碼中,CDerived類(lèi)通過(guò)using CBase::CBase語(yǔ)句,使得它可以直接使用CBase類(lèi)中的所有公有和受保護(hù)的構(gòu)造函數(shù)。這樣,在創(chuàng)建CDerived對(duì)象時(shí),可以根據(jù)傳入的參數(shù)類(lèi)型調(diào)用對(duì)應(yīng)的基類(lèi)構(gòu)造函數(shù)來(lái)進(jìn)行初始化。同時(shí),CDerived類(lèi)還可以擁有自己的構(gòu)造函數(shù),以處理新增成員變量的初始化和其他特殊邏輯。