<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # Item 5: 了解 C++ 為你偷偷地加上和調用了什么函數 作者:Scott Meyers 譯者:fatalerror99 (iTePub's Nirvana) 發布:http://blog.csdn.net/fatalerror99/ 一個 empty class(空類)什么時候將不再是 empty class(空類)?答案是當 C++ 搞定了它。如果你自己不聲明一個 copy constructor(拷貝構造函數),一個 copy assignment operator(拷貝賦值運算符)和一個 destructor(析構函數),編譯器就會為這些東西聲明一個它自己的版本。此外,如果你自己根本沒有聲明 constructor(構造函數),編譯器就會為你聲明一個 default constructor(缺省構造函數)。所有這些函數都被聲明為 public 和 inline(參見 Item 30)。作為結果,如果你寫 ``` class Empty{}; ``` 在本質上和你這樣寫是一樣的: ``` class Empty { public: Empty() { ... } // default constructor Empty(const Empty& rhs) { ... } // copy constructor ~Empty() { ... } // destructor — see below // for whether it's virtual Empty& operator=(const Empty& rhs) { ... } // copy assignment operator }; ``` 這些函數只有在它們被需要的時候才會生成,但是并不需要做太多的事情,就會用到它們。下面的代碼會促使每一個函數生成: ``` Empty e1; // default constructor; // destructor Empty e2(e1); // copy constructor e2 = e1; // copy assignment operator ``` 假設編譯器為你寫了這些函數,那么它們做些什么呢?default constructor(缺省構造函數)和 destructor(析構函數)主要是給編譯器一個地方放置 "behind the scenes" code(“幕后”代碼)的,諸如 base classes(基類)和 non-static data members(非靜態數據成員)的 constructors(構造函數)和 destructor(析構函數)的調用。注意,生成的 destructor(析構函數)是 non-virtual(非虛擬)的(參見 Item 7),除非它所在的 class(類)是從一個 base class(基類)繼承而來,而 base class(基類)自己聲明了一個 virtual destructor(虛擬析構函數)(這種情況下,函數的 virtualness(虛擬性)來自 base class(基類))。 對于 copy constructor(拷貝構造函數)和 copy assignment operator(拷貝賦值運算符),compiler-generated versions(編譯器生成版本)只是簡單地從 source object(源對象)拷貝每一個 non-static data member(非靜態數據成員)到 target object(目標對象)。例如,考慮一個 NamedObject template(模板),它允許你將名字和類型為 T 的 objects(對象)聯系起來的: ``` template<typename T> class NamedObject { public: NamedObject(const char *name, const T& value); NamedObject(const std::string& name, const T& value); ... private: std::string nameValue; T objectValue; }; ``` 因為 NamedObject 中聲明了一個 constructors(構造函數),編譯器就不會再生成一個 default constructor(缺省構造函數)。這一點很重要,它意味著如果你小心地設計一個 class(類),使它需要 constructor arguments(構造函數參數),你就不必顧慮編譯器會不顧你的決定,輕率地增加一個不需要參數的 constructors(構造函數)。 NamedObject 既沒有聲明 copy constructor(拷貝構造函數)也沒有聲明 copy assignment operator(拷貝賦值運算符),所以編譯器將生成這些函數(如果需要它們的話)。看,這就是 copy constructor(拷貝構造函數)的用法: ``` NamedObject<int> no1("Smallest Prime Number", 2); NamedObject<int> no2(no1); // calls copy constructor ``` 編譯器生成的 copy constructor(拷貝構造函數)一定會用 no1.nameValue 和 no1.objectValue 分別初始化 no2.nameValue 和 no2.objectValue。nameValue 的類型是 string,標準 string 類型有一個 copy constructor(拷貝構造函數),所以將通過以 no1.nameValue 作為參數調用 string 的 copy constructor(拷貝構造函數)初始化 no2.nameValue。而另一方面,NamedObject&lt;int&gt;::objectValue 的類型是 int(因為在這個 template instantiation(模板實例化)中 T 是 int),而 int 是 built-in type(內建類型),所以將通過拷貝 no1.objectValue 的每一個二進制位初始化 no2.objectValue。 編譯器為 NamedObject&lt;int&gt; 生成的 copy assignment operator(拷貝賦值運算符)本質上也會有同樣的行為,但是,通常情況下,只有在結果代碼合法而且有一個合理的可理解的巧合時,compiler-generated(編譯器生成)的 copy assignment operator(拷貝賦值運算符)才會有我所描述的行為方式。如果這兩項檢測中的任一項失敗了,編譯器將拒絕為你的 class(類)生成一個 operator=。 例如,假設 NamedObject 如下定義,nameValue 是一個 reference to a string(引向一個字符串的引用),而 objectValue 是一個 const T: ``` template<class T> class NamedObject { public: // this ctor no longer takes a const name, because nameValue // is now a reference-to-non-const string. The char* constructor // is gone, because we must have a string to refer to. NamedObject(std::string& name, const T& value); ... // as above, assume no // operator= is declared private: std::string& nameValue; // this is now a reference const T objectValue; // this is now const }; ``` 現在,考慮這里會發生什么: ``` std::string newDog("Persephone"); std::string oldDog("Satch"); NamedObject<int> p(newDog, 2); // when I originally wrote this, our // dog Persephone was about to // have her second birthday NamedObject<int> s(oldDog, 36); // the family dog Satch (from my // childhood) would be 36 if she // were still alive p = s; // what should happen to // the data members in p? ``` assignment(賦值)之前,p.nameValue 和 s.nameValue 都引向 string objects(對象),雖然并非同一個。那個 assignment(賦值)對 p.nameValue 產生了什么影響呢?assignment(賦值)之后,p.nameValue 所引向的 string 是否就是 s.nameValue 所引向的那一個呢,也就是說,reference(引用)本身被改變了?如果是這樣,就違反了常規,因為 C++ 并沒有提供使一個 reference(引用)引向另一個 objects(對象)的方法。換一種思路,是不是 p.nameValue 所引向的那個 string objects(對象)被改變了,從而影響了其他 objects(對象)—— pointers(指針)或 references(引用)持續指向的那個 string,也就是,賦值中并沒有直接涉及到的對象?這是 compiler-generated(編譯器生成)的 copy assignment operator(拷貝賦值運算符)應該做的事情嗎? 面對這個難題,C++ 拒絕編譯代碼。如果你希望一個包含 reference member(引用成員)的 class(類)支持 assignment(賦值),你必須自己定義 copy assignment operator(拷貝賦值運算符)。對于含有 const members(const 成員)的 classes(類),編譯器會有類似的行為(就像上面那個改變后的 class(類)中的 objectValue)。改變 const members(const 成員)是不合法的,所以編譯器隱式生成的 assignment function(賦值函數)無法確定該如何對待它們。最后,如果 base classes(基類)將 copy assignment operator(拷貝賦值運算符)聲明為 private,編譯器拒絕為從它繼承的 derived classes(派生類)生成 implicit copy assignment operators(隱式拷貝賦值運算符)。畢竟,編譯器為派生類生成的 copy assignment operator(拷貝賦值運算符)也要處理其 base class parts(基類構件)(參見 Item 12),但如果這樣做,它們當然無法調用那些 derived classes(派生類)無權調用的 member functions(成員函數)。 Things to Remember * 編譯器可以隱式生成一個 class(類)的 default constructor(缺省構造函數),copy constructor(拷貝構造函數),copy assignment operator(拷貝賦值運算符)和 destructor(析構函數)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看