【C++】C++問題——類模板分離編譯、函數對象、智能指標

來源:互聯網
上載者:User

標籤:c++

C++類模板的分離編譯

過去很多類模板都是整個類連同實現都放在一個標頭檔裡,像STL庫就是遵循這樣的策略來實作類別模板的。現在的標準正試圖矯正這種局面。
在實現中又許多函數模板。這意味著每個函數都必須包含模板聲明,並且在使用範圍操作符的時候,類的名稱必須通過模板變數來執行個體化。
比如一個operator=的代碼:

template <typename Object>const MemoryCell <Object> &MemoryCell<Object>::operator=(const MemoryCell<Object> & rhs){    if(this != &rhs)    storeValue = rhs.storedValue;    return *this;}
標頭檔內容

將聲明和實現都放在標頭檔中,對於類是行不通的,因為如果幾個不同的源檔案都有處理這個標頭檔的包含指令的話,就會出現重複定義函數的情況。但是,如果在標頭檔裡的知識模板而不是真實的類,就不會有問題。

函數對象

在一個函數的編寫中,需要像接受參數一樣接受比較函數,用該比較函數來決定兩個對象的大小。
使用這種方法的原因是,將比較的規則從對象中剝離出來,用一個比較函數來決定。
一個如傳遞參數一樣傳遞函數的巧妙辦法是:定義一個包含零個資料和一個成員函數的類,然後傳遞這個類的執行個體。從效果上看就是,通過將其放在對象中實現了函數的傳遞,該對象通常稱為函數對象。
舉例:
findMax函數獲得第二個形參,該形參為泛型型別。為使findMax模板可以無誤地擴充,泛型型別必須含有名為isLessThan的成員函數。該成員函數獲得第一個泛型型別的兩個形參,並返回一個bool值。

template <typename T, typename Comparator>const T & findMax(const vector<T> & arr, Comparator cmp){    int maxIndex = 0;    for(int i=1;i<arr.size();i++)    if(cmp.isLessThan(arr[maxIndex],arr[i]))        maxIndex = i;    return arr[maxIndex];}class CaseInsensitiveCompare{public:    bool isLessThan(const string & lhs, const string & rhs) const    {        return stricmp(lhs.c_str(), rhs.c_str()) < 0;    }};int main(){    vector<string> arr(3);    arr[0] = "ZERbad";    arr[1] = "alligator";    arr[2] = "crocodile";    cout << findMax(arr, CaseInsensitiveCompare()) << endl;    return 0;}
智能指標

包含指標的類需要特別注意複製控制,原因是複製指標時只複製指標的地址,而不會複製指標指向的對象。
當類中有指標成員時,一般有兩種方式來管理指標成員:一是採用值型的方式管理,每個類對象都保留一份指標指向的對象的拷貝;另一種更優雅的方式是使用智能指標,從而實現指標指向的對象的共用。
智能指標(smart pointer)的一種通用實現技術是使用引用計數(reference count)。智能指標類將一個計數器與類指向的對象相關聯,引用計數跟蹤該類有多少個對象的指標指向同一對象。

管理指標成員

設計具有指標成員的類時,類的設計者必須首先需要決定的是該指標應提供什麼行為。將一個指標複製到另一個指標時,兩個指標指向同一對象。當兩個指標指向同一對象時,可能使用任一指標改變基礎對象。類似地,很可能一個指標刪除了一個對象時,另一指標的使用者還認為基礎對象仍然存在。
大多數C++類採用以下三種方法之一管理指標成員:

  1. 指標成員採用常規指標型行為。這樣的類具有指標的所有缺陷但無需特殊的複製控制。
  2. 類可以實現所謂的“智能指標”行為。指標所指向的對象時共用的,但類能夠防止懸垂指標。
  3. 類採用值型行為。指標所指向的對象時唯一的,由每個類對象獨立管理。
懸垂指標

具有指標成員且使用預設合成複製建構函式的類,因為類的複製時,直接複製指標。使用者必須保證只要類對象存在,該指標指向的對象就存在。如果之前指向的對象不再存在了,此類指標稱為懸垂指標。結果未定義,往往導致程式錯誤,難以檢測。我們可以引入智能指標來防止懸垂指標的出現。

關於智能指標的具體內容請移步智能指標類和OpenCV的Ptr模板類

non-const成員函數調用const成員函數

在operator[]函數的編寫中,我們要做的其實是實現其機能一次,並使用它兩次。
你必須令其中一個調用另一個。這促使我們將常量性轉除
當const operator[]完全做了non-const版本該做的一切時,如果將傳回值的const轉除是安全的,因為不論誰調用non-const operator[]都一定有個non-const對象,否則就不能調用non-const函數。所以令non-const operator調用其const函數式一個避免代碼重複的安全做法。

class A{public:    const char& operator[](std::size_t position) const    {        ...        ...        return text[position];    }    char& operator[](std::size_t position)    {        return        const_cast<char &>(            static_cast<const A&>(*this)[position]        );    }private:    std::string text;}

要讓non-const operator[]調用const operator[],但non-const operator[]內部如果只是單純調用operator[],會遞迴調用自己。所以我們必須明確指出調用的是const operator[]。這裡將*this從原始類型A&轉型為const A&。這樣為 *this 添加const。這裡我們使用static_cast進行安全轉型。
第二次則是從const operator[]的傳回值中移除const。這裡只能藉助const_cast完成。

如果在const函數內調用non-const函數,就會改變對象的邏輯狀態,所以const成員函數調用non-const成員函數是一種錯誤行為;而non-const成員函數本來就可以對其對象做任何動作,所以在其中調用一個const成員函數並不會帶來風險。

轉載請註明作者Jason Ding及其出處
Github部落客頁(http://jasonding1354.github.io/)
CSDN部落格(http://blog.csdn.net/jasonding1354)
簡書首頁(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
百度搜尋jasonding1354進入我的部落客頁

【C++】C++問題——類模板分離編譯、函數對象、智能指標

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.