<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    PS,1880后程序員

    看不完的牙,寫不完的程序,跑不完的步。
    隨筆 - 97, 文章 - 34, 評論 - 10, 引用 - 0
    數據加載中……

    C++ Primer 之 讀書筆記 第十二章

     

    Classes

    12.1. 類的定義和聲明 Class Definitions and Declarations

    類定義

    大師僅僅寫了這么一個類定義的簡單的例子,卻有這么多的東西可以說說啊

    class Sales_item {

    public:

        // operations on Sales_item objects

        double avg_price() const;

        bool same_isbn(const Sales_item &rhs) const

            { return isbn == rhs.isbn; }

        // default constructor needed to initialize members of built-in type

        Sales_item(): units_sold(0), revenue(0.0) { }

    private:

        std::string isbn;

        unsigned units_sold;

        double revenue;

    };

    double Sales_item::avg_price() const

    {

        if (units_sold)

            return revenue/units_sold;

        else

            return 0;

    }

    ·       Member: data, functions or type definitions.

    ·       構造函數Constructors初始化:

    // default constructor needed to initialize members of built-in type

    Sales_item(): units_sold(0), revenue(0.0) { }

    這種寫法是初始化內置數據類型。

    ·                 const:表示functions不會修改數據成員。這可以用在查詢或者判斷類型的functions上。

    ·       成員函數member functions必須在類的內部聲明,成員函數的定義是否放在類定義里面是可選的。如果放在類里面,那么

    數據抽象和封裝Data Abstraction and Encapsulation

    類背后蘊涵的基本思想是數據抽象和封裝。(The fundamental ideas behind classes are data abstraction and encapsulation.)數據抽象這種技術依賴于接口和實現的分離。(Data abstraction is a programming (and design) technique that relies on the separation of interface and implementation.

    多么精煉的話,包含了面向對象的深刻含義。大師啊。

    類的用戶(user of class)是誰?程序員programmeruser of class就如同user of application

    類的用戶最關心啥?最關心的是接口。

    關于類定義的更多內容 more on class definitions

    使用Typedef簡化類

    class Screen {

    public:

        // interface member functions

        typedef std::string::size_type index;

    private:

        std::string contents;

        index cursor;

        index height, width;

    };

    注意:

    typedef是放在public部分的,這樣Screen的用戶都能夠使用這個typedef

    成員函數可被重載Member Functions May Be Overloaded

    顯式指定 inline 成員函數Explicitly Specifying inline Member Functions

    成員函數定義為inline。這個定義即可以在函數聲明里,也可以在類定義之外。在類聲明和類定義里把函數指定為inline都是合法的。(It is legal to specify inline both on the declaration and definition.

    類聲明與類定義

    類定義一般要放在頭文件中。

    類聲明后,即使沒有類定義,也可以作為引用或者指針來使用:

    class LinkScreen {

           Screen window;

           LinkScreen *next;

           LinkScreen *prev;

    };

    LinkScreen定義完成之前,我們就定義了指向LinkScreen類型的指針。

    這里引入了兩個基本感念:

    前向聲明forward declaretion

    class Screen; //definition of the Screen class

    這就是一個前向聲明。表示Screen是一個類類型(class type)。

    不完全類型incompete type:在前向聲明之后,類定義之前Screen就是一個不完全類型。意思是說知道Screen是個類型,但是不知道這個類型包括那些成員(members)。不完全類型只能用在有限的幾種方式,它可以用來定義這種類型的指針或者是引用,也可以用在把這種類類型作為形參或者返回值類型的函數聲明。(An incomplete type may be used to define only pointers or references to the type or to declare (but not define) functions that use the type as a paremeter or return type.

    在創建某個類類型的對象前,這個類類型必須完整定義。這樣編譯器餐能夠知道要為這種類型的對象保留多大的存儲空間。

    12.2 隱含的this指針 The Implicit this Pointer

    何時使用this

    簡單的說,就是當我們需要引用整個對象而不是對象中的成員的時候。最常見的情況是在返回值是被調用的對象的引用的函數里。(when we need to refer to the object as a whole rather than to a member of the object. The most common case where we must use this is in functions that return a reference to the object on which they were invoked.

    this是指針,因此如果返回值是當前對象的引用,那么返回語句一定是:

    return *this;

    剛開始看到這個的時候,總是和Java搞混,因為Java是沒有指針,所以返回的只能是this,顯式使用的時候也是this

    const成員函數里返回*this

    這里有兩個規則:

    1. 對于一般的非const成員函數,this的類型是一個const pointer。這意味我們可以修改this指向的對象的值,但是不能修改this保存的地址。(In an ordinary nonconst member function, the type of this is a const pointer to the class type. We may change the value to which this points but cannot change the address that this holds.
    2. 對于const成員函數,this的類型是一個指向const 對象的const pointer。這意味我們既不可以修改this指向的對象的值,也不能修改this保存的地址。(In a const member function, the type of this is a const pointer to a const class-type object. We may change neither the object to which this points nor the address that this holds.

    基于const的重載

    可以定義兩個操作,一個是const,另一個不是,這也算是重載。

    class Screen {

     public:

         // interface member functions

         // display overloaded on whether the object is const or not

         Screen& display(std::ostream &os)

                       { do_display(os); return *this; }

         const Screen& display(std::ostream &os) const

                       { do_display(os); return *this; }

     private:

          // single function to do the work of displaying a Screen,

          // will be called by the display operations

          void do_display(std::ostream &os) const

                            { os << contents; }

          // as before

     };

    這樣const對象使用const成員函數;非const對象可以使用任一成員函數,不過最好還是使用非const的成員函數。

    對比下面的例子(基于指針形參是否指向const的函數重載):

    Record lookup(Account&);

    Record lookup(const Account&); // new function

    可變數據成員Mutable Data Members

    即使對象是const,有時我們也希望其中的某些數據成員是可以修改的,這就引出了mutable

    可變數據成員絕不是const,即使對象是const。這樣const的成員函數也是可以修改可變數據成員的。

    定義:

    class Screen {

     public:

     // interface member functions

     private:

         mutable size_t access_ctr; // may change in a const members

         // other data members as before

     };

    12.3 類的作用范圍

    12.4構造函數Constructors

    構造函數不能聲明為const

    建議的方法:使用構造函數初始化式Constructor Initializer

    // recommended way to write constructors using a constructor initializer

    Sales_item::Sales_item(const string &book):

         isbn(book), units_sold(0), revenue(0.0) { }

    Constructor Initializer

    以下是正確的寫法:

    // recommended way to write constructors using a constructor initializer

    Sales_item::Sales_item(const string &book):

         isbn(book), units_sold(0), revenue(0.0) { }

    但是這種寫法乍一看似乎和下面不使用Constructor Initializer的效果一樣:

    // legal but sloppier way to write the constructor:

    // no constructor initializer

    Sales_item::Sales_item(const string &book)

    {

        isbn = book;

        units_sold = 0;

        revenue = 0.0;

    }

    NONO,不一樣。后一種寫法那就像郭德綱相聲說的房都燒沒了,就剩下個防盜門,于謙還開門進去。isbn的初始化是在構造函數執行之前完成的。上面這個寫法先用缺省的string的構造函數初始化isbn,在構造函數的函數體執行時,isbn又重新賦值為book。沒效率啊!但是對于內置類型來說,兩種方式無論是在結果上還是在性能上又都是沒有區別的。

    構造函數的執行分成兩個步驟:

    1. 初始化階段,類的數據成員是在這個階段初始化的。
    2. 一般計算階段,這就是指構造函數函數體的執行。

    在計算階段前初始化階段就開始了。(Initialization happens before the computation phase begins.

    在一些特定的情況下必須使用Constructor Initializer,這些特殊的情況包括:

    1. 數據成員沒有缺省的構造函數
    2. 數據成員是const或者是引用

    for example:

    // legal but sloppier way to write the constructor:

    // no constructor initializer

    class ConstRef {

     public:

         ConstRef(int ii);

     private:

         int i;

         const int ci;

         int &ri;

     };

     // no explicit constructor initializer: error ri is uninitialized

     ConstRef::ConstRef(int ii)

     {              // assignments:

          i = ii;   // ok

          ci = ii; // error: cannot assign to a const

          ri = i;   // assigns to ri which was not bound to an object

     }

    正確寫法:只有用constructor initializer才有機會對const和引用進行初始化。

    ConstRef::ConstRef(int ii): i(ii), ci(i), ri(ii) { }

    成員初始化順序

    成員的初始化順序就是成員的定義的順序。第一個定義的成員第一個初始化,然后是下一個,以此類推。(The order in which members are initialized is the order in which the members are defined. The first member is initialized first, then the next, and so on.

    類類型的數據成員的初始化Initializers for Data Members of Class Type

    Constructor Initializer初始化式使用類的某一個構造函數來完成。

    // alternative definition for Sales_item default constructor

    Sales_item(): isbn(10, '9'), units_sold(0), revenue(0.0) {}

    缺省構造函數

    只有在類沒有定義任何一個構造函數時,編譯器才會自動生成缺省的構造函數。

    隱式類類型轉換 Implicit Class-Type Conversions

    12.5. 友元Friends

    友元就是允許其它特定的類和方法來訪問它的非public的成員。(The friend mechanism allows a class to grant access to its nonpublic members to specified functions or classes.

    友元定義:

    class Screen {

         // Window_Mgr members can access private parts of class Screen

         friend class Window_Mgr;

         // ...rest of the Screen class

     };

    友元不是類的成員,但是他們是類的接口的組成部分。(even if they are not members of the class, they are "part of the interface" to the class.

    友元可以是:

    類的成員函數

    class Screen {

    // Window_Mgr must be defined before class Screen

    friend Window_Mgr&

         Window_Mgr::relocate(Screen::index r, Screen::index c,

                          Screen& s);

         // ...rest of the Screen class

     }

    一般的非成員函數

    友元聲明和范圍

    友元聲明和友元定義之間存在的相互依賴關系使得我們小心地構造類。再看上面的例子:

    Window_Mgr必須要的Screen前定義。但是成員方法relocate要在Screen定義后才能定義。靠,這就像是先有蛋還是先有雞一樣擰巴。

    class Screen {

    // Window_Mgr must be defined before class Screen

    friend Window_Mgr&

         Window_Mgr::relocate(Screen::index r, Screen::index c,

                          Screen& s);

         // ...rest of the Screen class

     }

    12.6. static 類成員static Class Members

    這句話是對static class member的最重要的解釋:

    靜態數據成員獨立于類的任何對象而存在,每個靜態數據成員是和類相關的對象,而不是和類的對象相關。(a static data member exists independently of any object of its class; each static data member is an object associated with the class, not with the objects of that class.

    使用靜態數據成員的好處

    static成員的名字的作用范圍是類,因此可以避免和其它的類的成員或者全局對象的名字的沖突。

    強制進行封裝。static成員可以是private的,而全局對象是不可以的。

    如果把static成員關聯到某個特殊的類上,這樣易于閱讀代碼。

    靜態成員函數static member function

    在靜態成員函數(static member function)中是不能使用this指針的。這其實很好理解,因為this指針指向的是對象,而靜態成員函數并不屬于任何的對象。

    靜態數據成員static data members

    靜態數據成員可以是任何的類型:const,引用reference,數組,指針類。

    class Account {

    public:

        // interface functions here

        void applyint() { amount += amount * interestRate; }

        static double rate() { return interestRate; }

        static void rate(double); // sets a new rate

    private:

        std::string owner;

        double amount;

        static double interestRate; //這是聲明

        static double initRate();

    };

    // define and initialize static class member,這是定義

    double Account::interestRate = initRate();

    以上是一個完整的static的定義,要注意以下幾點:

    1.      靜態數據成員要在類定義體之外來定義。(static data members must be defined (exactly once) outside the class body.

    2.      靜態成員不能通過構造函數進行初始化,而是在定義的時候就完成了初始化。(static members are not initialized through the class constructor(s) and instead should be initialized when they are defined.

    3.      關鍵字static只是用在類體內的成員聲明,而當在類的外面的對靜態數據成員進行定義時,就不要再使用關鍵字static。(The static keyword, however, is used only on the declaration inside the class body. Definitions are not labeled static.

    整型類型的靜態數據成員可以在類定義體內直接定義,只要是初始化值是常量表達式。

    a const static data member of integral type can be initialized within the class body as long as the initializer is a constant expression

    period的定義就是這樣:

    class Account {

     public:

          static double rate() { return interestRate; }

          static void rate(double); // sets a new rate

     private:

          static const int period = 30; // interest posted every 30 days

          double daily_tbl[period]; // ok: period is constant expression

     };

    // definition of static member with no initializer;

    // the initial value is specified inside the class definition

    const int Account::period;

    注意:雖然period在類定義體內完成了初始化,但是還是要在類定義之外定義數據成員。(When a const static data member is initialized in the class body, the data member must still be defined outside the class definition.

    靜態成員不是類對象的一部分

    也正因為如此,對于非靜態成員的非法的使用方式,對于靜態成員來說就是合法的。例如:靜態成員的類型可以是它所屬類的類型。非靜態數據成員被嚴格限制只能是它所屬類的對象的引用或者是指針。(the type of a static data member can be the class type of which it is a member. A nonstatic data member is restricted to being declared as a pointer or a reference to an object of its class:

    class Bar {

     public:

          // ...

     private:

          static Bar mem1; // ok

          Bar *mem2;       // ok

          Bar mem3;        // error

     };

    posted on 2009-06-16 09:17 amenglai 閱讀(864) 評論(1)  編輯  收藏 所屬分類: C++ Primer 之 讀書筆記

    評論

    # re: C++ Primer 之 讀書筆記 第十二章   回復  更多評論   

    你好,看到你的博客寫了四年,我覺得樓主肯定是一位真正的大牛和一個懂得堅持的人。我先在在看C++ primer,類以后我很是懼怕,不知道前輩能否指點一二,講講自己的讀書心得!
    2013-09-14 21:56 | 水目沾
    主站蜘蛛池模板: 老湿机一区午夜精品免费福利| 亚洲熟妇av午夜无码不卡| 无码AV动漫精品一区二区免费| 一二三四视频在线观看中文版免费| 亚洲国产一区二区a毛片| a级毛片免费在线观看| 九月丁香婷婷亚洲综合色| 免费无码又爽又刺激高潮软件| 日本精品久久久久久久久免费| 国产免费黄色大片| 丁香六月婷婷精品免费观看| 亚洲性日韩精品一区二区三区| 一级有奶水毛片免费看| 亚洲av无码精品网站| 美丽的姑娘免费观看在线播放| 精品国产日韩久久亚洲| 国产免费131美女视频| 永久免费精品影视网站| 亚洲国产精品VA在线看黑人 | 美女视频黄的全免费视频| 激情五月亚洲色图| 免费一级毛片正在播放| 中文在线免费看视频| 亚洲第一成年网站大全亚洲| 成年轻人网站色免费看| 又粗又长又爽又长黄免费视频| 日韩亚洲人成在线综合日本| 99久久国产热无码精品免费| 亚洲色婷婷综合久久| 24小时免费看片| 精品国产日韩亚洲一区在线| 亚洲无线码一区二区三区| 亚洲一级毛片免费观看| 国产亚洲美女精品久久久久| 亚洲国产一二三精品无码| 国产又黄又爽又猛免费app| 草久免费在线观看网站| 亚洲永久中文字幕在线| 五月天婷亚洲天综合网精品偷| 久久精品无码专区免费东京热| 亚洲国产欧美日韩精品一区二区三区 |