the others[GeekBand]

1 類類型轉(zhuǎn)換

在C++中,類只要滿足特定的條件就可以從類對象轉(zhuǎn)換到基本類型或其他類類型對象,也可以從基本類型或其他類類型對象轉(zhuǎn)換到該類對象。1.1和1.2節(jié)講述只兩種轉(zhuǎn)換的操作方法以及注意事項。

1.1 class到其他對象

一個class對象要轉(zhuǎn)換到其他類型的對象,需要重載類型轉(zhuǎn)換操作符(Conversion Operator)。類型轉(zhuǎn)換操作符是一種特殊的成員函數(shù),它負(fù)責(zé)將一個類類型的值轉(zhuǎn)換成其他類型。類型轉(zhuǎn)換操作符的一般形式:
operator type() const;
**
注意:
1.類型轉(zhuǎn)換操作符沒有返回值;
2.type可以是除了void之外,任意能夠作為函數(shù)返回值的類型;
3.一般類型轉(zhuǎn)換操作符都不會修改類數(shù)據(jù)成員的值,因此一般聲明為const;
4.類型轉(zhuǎn)換操作符是不可以帶有參數(shù)的;
5.類型轉(zhuǎn)換操作符必須是類的成員函數(shù)。
**
在實現(xiàn)上,一般很少有類提供類型轉(zhuǎn)換操作符,但是有一個例外,類定義向bool類型的轉(zhuǎn)換還是比較常見的。比如我們經(jīng)常使用輸入輸出流,文件流和字符流都定義了從類對象到bool對象的轉(zhuǎn)換。有了這種轉(zhuǎn)換我們就可以很方便的編寫判斷文件打開是否成功、文件讀取/寫入是否成功的代碼,像 if(cin)或者while(cin >> val)。如果沒有這種轉(zhuǎn)換,對while的判斷我們可能就要這樣寫:

    while(1){
    cin >> val;
    if (cin.good()){//do someting.}
    }

相較之下,方便程度力見。在使用C++的語法元素上,標(biāo)準(zhǔn)庫是最有說服力的。因此,下面我們看下標(biāo)準(zhǔn)庫的basic_istream::sentry是如何實現(xiàn)類型轉(zhuǎn)換的。

template<typename _CharT, typename _Traits>
class basic_istream<_CharT, _Traits>::sentry
{
  // Data Members.
  bool _M_ok;
public:
  explicit
  sentry(basic_istream<_CharT, _Traits>& __is, bool __noskipws = false);
#if __cplusplus >= 201103L
  explicit
#endif
  operator bool() const
  { return _M_ok; }
};

從sentry的實現(xiàn)中,我們可以看到類型轉(zhuǎn)換操作符聲明上雖然沒有返回值,但是需要返回一個type類型的對象(這里就是bool)。
類型轉(zhuǎn)換操作符一般都是隱式進(jìn)行的,因此可能出現(xiàn)會產(chǎn)生意料之外的結(jié)果,為了限制編譯器在非bool上下文中進(jìn)行隱式轉(zhuǎn)換,C++11引入了顯式的類型轉(zhuǎn)換符,形式如下:
explicit operator type() const
通過在聲明中添加explicit關(guān)鍵字來要求編譯器只能在bool上下文中使用類型轉(zhuǎn)換。

1.2 其他對象到class

通過定義只帶一個參數(shù)的構(gòu)造函數(shù)可以實現(xiàn)其他對象到類對象的隱式類型轉(zhuǎn)換。我們通過一個示例來看下如何編寫從其他類型到class對象的隱式轉(zhuǎn)換。
代碼

#include <iostream>
using namespace std;
class A
{
    double m_data;
public:
    A(double x):m_data(x){cout << "A::ctor(x)" << endl;}
    void print()const{cout << m_data << endl;}
};
int main()
{
    A a(1);
    a.print();  //輸出a=1
    a = 3;
    a.print();  //輸出a=3
}

程序輸出結(jié)果:

A::ctor(x)
1
A::ctor(x)
3

從程序的輸出結(jié)果可以看出在執(zhí)行a=3時,編譯器會先調(diào)用構(gòu)造函數(shù)將數(shù)值3轉(zhuǎn)換成類A的對象,然后再執(zhí)行賦值操作。因此,我們可以用類似的方式來實現(xiàn)其他對象向類對象的隱式轉(zhuǎn)換。
雖然,編譯器的這種隱式類型轉(zhuǎn)換是很方便的,但是,我們有時候并不希望編譯器進(jìn)行隱式類型轉(zhuǎn)換,這時候可以在構(gòu)造函數(shù)的聲明前添加explicit關(guān)鍵字來阻止編譯器的隱式轉(zhuǎn)換。

2 like-classes

C++有兩種很特別的類,pointer like class和function like class。pointer like class的行為像指針,function like class的行為像函數(shù)。

2.1 pointer like class

pointer like class通過重載操作符*,->,++,--等其中的一部分或全部來使類具有像指針一樣的行為。pointer like class主要的用途有兩個:智能指針和迭代器。本文不打算從pointer like class用途的角度來描述,本文主要從操作符重載的角度來描述怎樣實現(xiàn)一個pointer like class.
一般pointer like class都要實現(xiàn)兩個操作符,解引用操作符(*)和箭頭操作符(->)。實現(xiàn)的示例如下:

template<typename T>
class SmartPtr{
    public:
        SmartPtr(T *p):px(p){}
        T& operator*(){return *px;}
        T* operator->(){return px;}
    private:
        T *px;
}

當(dāng)我們定義好類SmartPtr以后,我們就可以像指針一樣使用它。如:

struct s{int no;};
SmartPtr<s> sp = new s;

然后對sp我們可以進(jìn)行解引用*sp和訪問對象成員sp->no。
**
注意:
1.箭頭操作符必須是類成員函數(shù)。解引用操作符通常是類成員函數(shù)。
2.重載的箭頭操作符必須返回類的指針或者重載了箭頭操作符的摸個類的對象。
**

2.2 function like class

如果類重載了函數(shù)調(diào)用操作符,則我們就可以像函數(shù)一樣使用該類的對象,因此我們稱這種類為function like class.由于類可以存儲狀態(tài)因此會比一般的函數(shù)更加靈活。
語法:
return-type operator()(param_type1 param1, param_type2 param2,...);
注意:函數(shù)調(diào)用操作符必須是成員函數(shù)。
我們來看一個示例:

struct absInt{
    int operator()(int x){
        return x > 0 ? x : -x;
    }
}

3 引用

3.1 語法

引用定義的一般形式為type& var = defined_var;或者consts type& var = defined_var;
引用是變量的別名,因此引用在定義的時候就要進(jìn)行初始化。當(dāng)使用引用時就和使用變量是一致。如下:

int x = 3;
int &r = x;  //定義引用
r = 5;   //對引用復(fù)制就是對變量x復(fù)制,此時x的值就是5.

3.2 常見用途及注意事項

1.很少用于變量聲明,一般用于參數(shù)傳遞和返回類型的描述。
2.引用類型的&符號并不能作為函數(shù)簽名
3.引用定義時就要進(jìn)行初始化。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容