• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 183,  comments - 10,  trackbacks - 0
             

            圖形
            矩形、正方形、圓形
            計算面積、面積輸出

            ·面向對象設計,類?
            ·實現功能?
            ·運行時多態性測試?

             1 #include <iostream>
             2 using namespace std;
             3 
             4 class Shape
             5 {
             6 protected:
             7     double area;
             8 public:
             9     virtual double getArea() const = 0;
            10     virtual void   showArea()
            11     {
            12         cout << area << endl;
            13     }
            14     // friend ostream& operator << (ostream& out, const Shape& s);
            15 };
            16 
            17 ostream& operator << (ostream& outconst Shape& s)
            18 {
            19     out << s.getArea();
            20     return out;
            21 }
            22 
            23 class Rectangle : public Shape
            24 {
            25 private:
            26     double x;
            27     double y;
            28 public:
            29     Rectangle(double i = 0.0double j = 0.0) : x(i), y(j)
            30     {
            31         area = x * y;
            32     }
            33     virtual double getArea() const
            34     {
            35         return area;
            36     }
            37 };
            38 
            39 class Square : public Shape
            40 {
            41 private:
            42     double x;
            43 public:
            44     Square(double i = 0.0) : x(i)
            45     {
            46         area = x * x;
            47     }
            48     virtual double getArea() const
            49     {
            50         return area;
            51     }
            52 };
            53 
            54 class Circle : public Shape
            55 {
            56 private:
            57     double r;
            58     static const double PI;
            59 public:
            60     Circle(double i = 0.0) : r(i)
            61     {
            62         area = PI * r * r;
            63     }
            64     virtual double getArea() const
            65     {
            66         return area;
            67     }
            68 };
            69 
            70 const double Circle::PI = 3.1415926;
            71 
            72 int main()
            73 {
            74     Shape* p;
            75     p = new Rectangle(45);
            76     cout << p->getArea() << endl;
            77     p->showArea();
            78     delete p;
            79     p = new Square(5);
            80     cout << p->getArea() << endl;
            81     p->showArea();
            82     delete p;
            83     p = new Circle(5);
            84     cout << p->getArea() << endl;
            85     p->showArea();
            86     delete p;
            87 
            88 
            89     Rectangle r(67);
            90     Square    s(7);
            91     Circle    c(9);
            92     cout << r << endl;
            93     cout << s << endl;
            94     cout << c << endl;
            95 
            96     return 0;
            97 }


            posted @ 2011-06-16 11:46 unixfy 閱讀(203) | 評論 (0)編輯 收藏
            賦值運算符的重載,有不同的方法,Effective C++ 中有一個條款對此介紹。
             1 #include <iostream>
             2 using namespace std;
             3 
             4 class MyString
             5 {
             6 private:
             7     unsigned len;
             8     char* data;
             9 public:
            10     MyString(const char* s = "");
            11     MyString(const MyString& s);
            12     MyString& operator = (const MyString& s);
            13     ~MyString();
            14 };
            15 
            16 MyString::MyString(const char* s)
            17 {
            18     len = strlen(s);
            19     data = new char[len + 1];
            20     if (data != 0)
            21     {
            22         strcpy(data, s);
            23     }
            24 }
            25 
            26 MyString::MyString(const MyString& s)
            27 {
            28     len = s.len;
            29     data = new char[len + 1];
            30     if (data != 0)
            31     {
            32         strcpy(data, s.data);
            33     }
            34 }
            35 
            36 MyString& MyString:: operator = (const MyString& s)
            37 {
            38     // 第一種方法,需要檢測自賦值,因為如果不檢測,則會造成當自賦值時,就直接將該對象的 data delete 了,也就是 s.data 被 delete 了。這時 s.data 是個懸置指針,所致內存極可能無效
            39     //
            40     //if (this != &s)
            41     //{
            42     //    delete [] data;
            43     //    len = s.len;
            44     //    data = new char[len + 1];
            45     //    if (data != 0)
            46     //    {
            47     //        strcpy(data, s.data);
            48     //    }
            49     //}
            50     //return *this;
            51     
            52     // 另一種方法, 不需要檢測自賦值
            53     // 這種方式需要做一個備份,自賦值情況下,temp 保持了另一份備份,即便 delete 了 data 還是留有一份
            54     // 非自賦值的情況下,對 s.data 所指的內容有了一個備份,然后 delete data,將 temp 賦予 data,這樣有了兩份 s.data,到達賦值的目的
            55     len = s.len;
            56     char* temp = new char[len + 1];
            57     if (temp != 0)
            58     {
            59         strcpy(temp, s.data);
            60     }
            61     delete [] data;
            62     data = temp;
            63     return *this;
            64 
            65     // 兩種方法的代價分析
            66     // 第一種方法,需要每次都要檢測是不是自賦值了,對于自賦值的情況,雖然檢測了,但是避免了備份,有利于自賦值的情況。但是對于非自賦值的情況,都需要額外的檢測,這種檢測是浪費的
            67     // 第二種方法,不管是自賦值還是非自賦值都需要備份,這種方法對于自賦值的情況,較第一種方法代價高些,但是對于非自賦值的情況它不需要檢測,也是做一個 copy 所以非自賦值的情況效率由于第一種方法
            68     // 也就是說第一種方法對于自賦值的情況好,第二種方法對于非自賦值的情況好。一般情況下,自賦值的情況并不經常出現,所以第一種檢測自賦值的操作很多情況下是多余的,所以相對第一種方法,第二種方法更好些。
            69 }
            70 
            71 MyString::~MyString()
            72 {
            73     len = 0;
            74     delete [] data;
            75 }
            76 
            77 int main()
            78 {
            79     MyString a("C++ Programming"), c("Hello");
            80     MyString b(a);
            81     c = b;
            82     cout << ". . ." << endl;
            83     return 0;
            84 }


            posted @ 2011-06-16 10:56 unixfy 閱讀(244) | 評論 (0)編輯 收藏

            Function 語意學

            static member functions 不可能做的
            ·存取 nonstatic 數據
            ·被聲明為 const
            ·virtual
            ·volatile

            this
            ·T* const this
            ·const T* const this

            名字的特殊處理 name mangling
            名字_類名_參數鏈表

            ((Point3d*)0)->object_count();

            virtual member functions
            虛擬成員函數
            任何問題都可以通過添加一個中間層來解決,實現多態就是通過添加了一個虛函數表和虛函數表指針這個中間層實現的

            多重繼承下的 virtual functions

            thunk
            address points

            virtual base class
            不要聲明 nonstatic data member

            構造函數的調用

            指向 member function 的指針
            double (Point::*pmf)();

            指向 virtual member functions 的指針
            ptr->z()
            (ptr->*pmf)();
            指向成員的指針實質是索引,而不是地址
            在我看來不管是 virtual member functions 的指針還是 nonvirtual member functions 的指針

            posted @ 2011-06-01 13:45 unixfy 閱讀(190) | 評論 (0)編輯 收藏

            第三章 Data 語意學

            class object 的大小
            ·支持語言特性(virtual)自動添加的 data members
            ·alignment 的需要

            empty virtual base class

            Data Member 的綁定
            ·成員完全可見,可以在后面
            ·類型定義應該放在最前面

            Data Member 的布局

            static const 成員初始化
            const 成員初始化

            Data Member 的存取
            static data members
            static data member 編碼
            name-mangling

            nonstatic data members

            origin._y = 0.0;
            &origin + (&Point3d::_y - 1);

            多態,指針或引用
            但是如果是 (*p).foo() ?

            繼承與 Data Member
            多態
            虛擬繼承

            ·virtual base class table
            ·virtual function table - offset

            對象成員的效率

            指向 Data Member 的指針

            posted @ 2011-05-28 13:22 unixfy 閱讀(87) | 評論 (0)編輯 收藏

            怎樣把函數模板聲明為類模板的友元

            給類模板聲明友元的函數模板有三種方式,分別為:
            第一種方式,在模板類內部聲明友元的函數模板
            第二種方式,在模板類內部聲明對應版本的友元函數模板實例化
             需要前置聲明
             這種方式是最為合理的方式
            第三種方式,在模板類內部直接聲明友元函數,不涉及函數模板
             這種情況只能在模板類內部一起把函數的定義寫出來,不能在外部實現,因為外部需要類型參數,而需要類型參數就是模板了
             其實這種情況相當于一般的模板類的成員函數,也就是相當于一個函數模板
             第二種方式也是一個函數模板,他們保持函數的參數類型和該模板類的實例一個類型
             第一種方式更為靈活,他不會要求參數類型與模板類實例是一個類型,但是一般情況下我們也是按照一個類型使用的。

             1 #include <iostream>
             2 using namespace std;
             3 
             4 //// 第一種方式,在模板類內部聲明友元的函數模板
             5 //template <typename T>
             6 //class C
             7 //{
             8 //private:
             9 //    T m[5];
            10 //public:
            11 //    template <typename U>
            12 //    friend void foo(const C<U>& T);
            13 //};
            14 //
            15 //template <typename T>
            16 //void foo(const C<T>& t)
            17 //{
            18 //    for (int i = 0; i < 5; ++i)
            19 //    {
            20 //        cout << t.m[i] << endl;
            21 //    }
            22 //}
            23 
            24 // 第二種方式,在模板類內部聲明對應版本的友元函數模板實例化
            25 // 需要前置聲明
            26 // 這種方式是最為合理的方式
            27 template <typename T>
            28 class C;
            29 
            30 template <typename T>
            31 void foo(const C<T>& t);
            32 
            33 template <typename T>
            34 class C
            35 {
            36 private:
            37     T m[5];
            38 public:
            39     friend void foo<T>(const C<T>& t);
            40 };
            41 
            42 template <typename T>
            43 void foo(const C<T>& t)
            44 {
            45     for (int i = 0; i < 5++i)
            46     {
            47         cout << t.m[i] << endl;
            48     }
            49 }
            50 
            51 //// 第三種方式,在模板類內部直接聲明友元函數,不涉及函數模板
            52 //// 這種情況只能在模板類內部一起把函數的定義寫出來,不能在外部實現,因為外部需要類型參數,而需要類型參數就是模板了
            53 //// 其實這種情況相當于一般的模板類的成員函數,也就是相當于一個函數模板
            54 //// 第二種方式也是一個函數模板,他們保持函數的參數類型和該模板類的實例一個類型
            55 //// 第一種方式更為靈活,他不會要求參數類型與模板類實例是一個類型,但是一般情況下我們也是按照一個類型使用的。
            56 //template <typename T>
            57 //class C
            58 //{
            59 //private:
            60 //    T m[5];
            61 //public:
            62 //    friend void foo(const C<T>& t)
            63 //    {
            64 //        for (int i = 0; i < 5; ++i)
            65 //        {
            66 //            cout << (t.m[i]) << endl;
            67 //        }
            68 //    }
            69 //};
            70 
            71 int main()
            72 {
            73     // C<int> c;
            74     C<double> c;
            75     foo(c);
            76     return 0;
            77 }


            http://topic.csdn.net/u/20100619/21/c32066bb-dacd-4938-8f95-7345a522b0f6.html
            http://topic.csdn.net/u/20100612/13/9365495d-b1d8-4e87-b704-23895acb1637.html
            http://www.cnblogs.com/wswqwps/archive/2008/10/25/1319320.html
            http://blog.csdn.net/dongzhongshu/archive/2011/02/22/6200466.aspx

            posted @ 2011-05-27 23:59 unixfy 閱讀(1883) | 評論 (0)編輯 收藏

            swap 到底做了什么
            swap 交換兩個內置數據類型的變量時,直接交換。
            swap 交換自定義類型對象時,如果里面沒有成員指針,直接交換各個對應成員。
            如果自定義類型中有指針成員,則是交換兩個指針的值,但是指針的指向的值得不到交換。
            正是由于這個原因,可以用 swap 進行重載 operator = 時避免自賦值情況,而是生產一個臨時對象,然后與本對象 swap 即可。

            關于重載 operator = 自賦值的情況,更詳細內容可以查看《Effective C++》
            實驗程序:

              1 #include <iostream>
              2 using namespace std;
              3 
              4 class Str
              5 {
              6 private:
              7     char* s_;
              8 public:
              9     Str(const char* s = "")
             10     {
             11         s_ = new char[strlen(s) + 1];
             12         if (s_ == 0)
             13         {
             14             cout << "test" << endl;
             15             exit(1);
             16         }
             17         strcpy(s_, s);
             18     }
             19     // 定義拷貝構造函數,這里會被用于 operator =,swap
             20     Str(const Str& rhs)
             21     {
             22         s_ = new char[strlen(rhs.s_) + 1];
             23         if (s_ == 0)
             24         {
             25             cout << "test" << endl;
             26             exit(1);
             27         }
             28         strcpy(s_, rhs.s_);
             29     }
             30     ~Str()
             31     {
             32         clear();
             33     }
             34     //// 常規的 operator = 重載實現方式,必須檢查自賦值
             35     //// 因為如果不自賦值檢驗,對于自賦值現象如果不調用 clear,則 s_ 在 new 之后就改變,rhs 也改變,原來的丟失,后來的也不是合法內容
             36     //// 如果調用 clear,不會內存泄露,但是 rhs 的內容被釋放掉,rhs 的內容也不是合法內容。
             37     //// 如果檢驗自賦值,而沒有 clear,原來 *this 的那塊內存會被丟失,造成內存泄露。
             38     //Str& operator = (const Str& rhs)
             39     //{
             40     //    if (this != &rhs)
             41     //    {
             42     //        clear();
             43     //        s_ = new char[strlen(rhs.s_) + 1];
             44     //        if (s_ == 0)
             45     //        {
             46     //            exit(1);
             47     //        }
             48     //        strcpy(s_, rhs.s_);
             49     //    }
             50     //    return *this;
             51     //}
             52 
             53     // 改進的 operator,先用一個 temp 保持 rhs,然后 swap
             54     // 這種方式不怕自賦值,因為如果是自賦值,也有一個備份 temp,操作值相同的兩個對象 *this 和 temp,直接交換不會影響結果
             55     // 如果不是自賦值,不是交換 *this 和 rhs,而是交換 *this 和 rhs 的一個復制品 temp,最終 *this 得到的值就是 rhs 的一個副本,完成賦值
             56     // 這種方式不用檢驗自賦值,所以可以省去每次調用時的自賦值檢驗,在基本上不會遇到自賦值檢驗的情況下,這種方法可以省去很多誤用的檢驗
             57     // 但是它會每次生成一個副本,這樣做的效率與原來的非自賦值一樣,而且還需要一個 swap,但是這種方式是異常安全的,用對象來管理資源,資源分配即初始化
             58     Str& operator = (const Str& rhs)
             59     {
             60         cout << "test" << endl;
             61         Str temp(rhs);
             62         // swap(*this, temp);
             63         // 這里會引起遞歸調用,因為 operator = 調用 swap,swap 內部又調用 operator = ,一直遞歸下去,直到棧溢出
             64         swap(s_, temp.s_);
             65         // Effective C++ 中提到,可以定義一個成員函數 swap,用于交換兩個對象對應的數據成員。這樣可以防止無限遞歸。
             66         // 另一種好的方式是除定義一個成員函數 swap 外,傳參類型為 值類型 T,這樣就可以直接交換返回。
             67         // 這些方法的前提都是要有定義拷貝構造函數的。
             68         return *this;
             69     }
             70 
             71     void clear()
             72     {
             73         delete [] s_;
             74     }
             75     void foo()
             76     {
             77         cout << s_ << endl;
             78     }
             79 };
             80 
             81 int main()
             82 {
             83     int a = 3, b = 5;
             84     swap(a, b);
             85     cout << a << endl;
             86     cout << b << endl;
             87 
             88     Str s1("abc");
             89     Str s2("xyz");
             90     s1.foo();
             91     s2.foo();
             92 
             93     swap(s1, s2);
             94     // 這里輸出兩個 test,我們得知,有兩個賦值操作
             95     // 可以推測 swap 的內部實現是 T t(s2), s2 = s1, s1 = t;
             96     s1.foo();
             97     s2.foo();
             98 
             99     s2 = s1;
            100     s1.foo();
            101     s2.foo();
            102 
            103     return 0;
            104 }


            posted @ 2011-05-27 22:14 unixfy 閱讀(892) | 評論 (0)編輯 收藏
            棧和堆是內存中的部分。安裝地址的變化規則,棧是向下生長的,堆是向上增長的。
            這里對棧和堆的地址生長情況做了一個實現。
            更好的內容有 Computer System:A Programmer's Perspective 《深入理解計算機系統》
             1 #include <iostream>
             2 using namespace std;
             3 
             4 int main()
             5 {
             6     int i = 1;
             7     int j = 2;
             8     int k = 3;
             9     cout << &<< endl;
            10     cout << &<< endl;
            11     cout << &<< endl;
            12     // 棧是向下生長的,所以地址遞減
            13 
            14     int a[3];
            15     cout << &a[0<< endl;
            16     cout << &a[1<< endl;
            17     cout << &a[2<< endl;
            18     // 棧還是向下生長的,但是對于一個數組來說從第一個元素到后面的元素
            19     // 其每個元素的地址是遞增的。所以最后一個元素是在最上面的,也就是
            20     // 與前面在棧上定義的元素挨著,第一個元素在最下面
            21 
            22     
            23     cout << a[3<< endl;
            24     cout << a[5<< endl;
            25     // 這里 a[5] 輸出 3,a + 5 將達到變量 k 的地址 &k,所以 *(a + 5) = k
            26 
            27 
            28     int* b = new int[3];
            29     cout << &b[0<< endl;
            30     cout << &b[1<< endl;
            31     cout << &b[2<< endl;
            32     // 堆是向上生長的,第一個元素在最下面
            33 
            34     // 不管是在堆還是在棧上的數組,數組中的元素的地址都是隨著元素的位
            35     // 置遞增而遞增的。
            36     // 只不過在棧上的元素順序與棧的增長方向相反,在堆上數組的元素的順
            37     // 序與堆的增長方向相同。
            38 
            39     return 0;
            40 }

            posted @ 2011-05-27 01:00 unixfy 閱讀(402) | 評論 (0)編輯 收藏

            關于訪問權限和繼承方式
            訪問權限有三種:public、protected、private
            繼承也有三種:public、protected、private,這里不考慮 virtual 繼承。
            繼承時的權限,不是針對本類內的訪問權限,而是針對該派生類的客戶端代碼(包括其派生類)的訪問權限。
            即是,對于基類中的 public、protected 成員,如果一個派生類 private 繼承自該基類,則這些成員還是可以在派生類中訪問的,只是不能在該派生類的客戶代碼中被直接訪問,或者在該派生類的派生類中直接訪問。
            也就是說,繼承的方式是針對派生類的客戶端代碼來講的,對派生類內部不起作用,不管是 public、protected、private 繼承,派生類中總是可以訪問基類中的 public、protected 成員,基類中的 private 成員永遠不能在派生類中直接訪問,不論通過哪種方式。
            歸納一下:
            成員訪問權限        繼承方式        派生類中能否訪問        派生類的派生類中        派生類的客戶端代碼
            public              public          能                      能                      能
            public              protected       能                      能                      不能
            public              private         能                      不能                    不能
            protected           public          能                      能                      不能
            protected           protected       能                      能                      不能
            protected           private         能                      不能                    不能
            private             public          不能                    不能                    不能
            private             protected       不能                    不能                    不能
            private             private         不能                    不能                    不能

            從這個表中,我們更能清除地看到成員訪問權限和繼承方式之間的組合,對派生類中的訪問、派生類的派生類中的訪問、派生類的客戶端代碼的訪問控制情況。


            繼承的方式是在原有基類訪問權限的基礎上,給在派生類的訪問權限又加了一個效應。取兩個中最嚴格的那個權限,這個取得的權限是派生類成員的訪問權限,而這種訪問權限對派生類的客戶端代碼和派生類的派生類代碼其訪問控制作用。

            posted @ 2011-05-27 00:20 unixfy 閱讀(456) | 評論 (0)編輯 收藏

            隊列的兩個主要操作:入隊列、出隊列
            棧的兩個主要操作:入棧、出棧
            入隊列對應入棧
            出隊列是出最早的,出棧是出最晚的

            使用 360 瀏覽器,有個不錯的功能是可以恢復標簽,你關閉一個標簽,這個標簽就會進入待恢復表,如果待恢復表慢了,新加標簽,最早的標簽會消失,這是 FIFO 隊列。
            但是如果點擊恢復標簽隊列,會恢復最近關閉的標簽,也就是最晚進入待恢復表中的標簽,所以這又是一種 LIFO 棧。

            待恢復表既具有添加標簽的 FIFO 隊列性質,又具有恢復標簽并移除標簽的 LIFO 棧性質。
            實現一個數據結構,使其既具有 FIFO 隊列的性質,又具有 LIFO 棧的性質。
            由于標簽有很多,這里使用循環表來實現這個數據結構,早期的標簽會隨著新加入的標簽被覆蓋。

            注意連續關閉兩個相同的標簽,第二次關閉時,不會將這個標簽存入待恢復表中。

            這個表主要有三個操作
            ·入隊列
            ·出隊列
            ·出棧
            沒有入棧,其實入棧也就是入隊列。

            實現:

              1 #include <iostream>
              2 using namespace std;
              3 
              4 class Table360
              5 {
              6 private:
              7     int  capacity_;
              8     int* data_;
              9     int  size_;
             10     int  head_;
             11     int  tail_;
             12 public:
             13     Table360(int c = 10) : capacity_(c)
             14     {
             15         data_ = new int[capacity_];
             16         if (data_ == 0)
             17         {
             18             exit(1);
             19         }
             20         memset(data_, 0sizeof (int* capacity_);
             21         size_ = 0;
             22         head_ = 0;
             23         tail_ = -1;
             24     }
             25     Table360(const Table360& t) : capacity_(t.capacity_)
             26     {
             27         data_ = new int[capacity_];
             28         if (data_ == 0)
             29         {
             30             exit(1);
             31         }
             32         memset(data_, 0sizeof (int* capacity_);
             33         size_ = t.size_;
             34         head_ = t.head_;
             35         tail_ = t.tail_;
             36         for (int i = 0; i < size_; ++i)
             37         {
             38             data_[(head_+i) % capacity_] = t.data_[(t.head_ + i) % t.capacity_];
             39         }
             40     }
             41     void swap_(Table360& t)
             42     {
             43         swap(capacity_, t.capacity_);
             44         swap(data_, t.data_);
             45         swap(size_, t.size_);
             46         swap(head_, t.head_);
             47         swap(tail_, t.tail_);
             48     }
             49     Table360& operator = (const Table360& t)
             50     {
             51         Table360 temp(t);
             52         swap_(temp);
             53         return *this;
             54     }
             55     ~Table360()
             56     {
             57         delete [] data_;
             58         capacity_ = 0;
             59         size_ = 0;
             60         head_ = 0;
             61         tail_ = 0;
             62     }
             63     int size()
             64     {
             65         return size_;
             66     }
             67     bool empty()
             68     {
             69         return size_ == 0;
             70     }
             71     int top()
             72     {
             73         return data_[head_];
             74     }
             75     void enQueue(int item)
             76     {
             77         if (size_ >= capacity_)
             78         {
             79             deQueue();
             80         }
             81         tail_ = (tail_ + 1% capacity_;
             82         data_[tail_] = item;
             83         ++size_;
             84         //if (size_ >= capacity_)
             85         //{
             86         //    head_ = (head_ + 1) % capacity_;
             87         //    --size_;
             88         //    tail_ = (tail_ + 1) % capacity_;
             89         //    data_[tail_] = item;
             90         //    ++size_;
             91         //}
             92         //else
             93         //{
             94         //    tail_ = (tail_ + 1) % capacity_;
             95         //    data_[tail_] = item;
             96         //    ++size_;
             97         //}
             98     }
             99     void deQueue()
            100     {
            101         head_ = ++head_ % capacity_;
            102         --size_;
            103     }
            104     // 其實沒有入棧操作,入棧即是入隊列
            105     void push(int item)
            106     {
            107         enQueue(item);
            108     }
            109     int pop()
            110     {
            111         int tmp = tail_;
            112         tail_ = (tail_ + capacity_ - 1% capacity_;
            113         --size_;
            114         return data_[tmp];
            115     }
            116     int stacktop()
            117     {
            118         return data_[tail_];
            119     }
            120 };
            121 
            122 int main()
            123 {
            124     Table360 t(20);
            125     cout << t.size() << endl;
            126     for (int i = 0; i < 100++i)
            127     {
            128         t.enQueue(i);
            129     }
            130     cout << t.size() << endl;
            131     // cout << t.top() << endl;
            132     while (!t.empty())
            133     {
            134         // cout << t.pop() << ' ';
            135         cout << t.stacktop() << ' ';
            136         t.pop();
            137     }
            138     cout << endl;
            139     return 0;
            140 }


            其他鏈接:
            http://zh.wikipedia.org/wiki/%E9%98%9F%E5%88%97
            http://zh.wikipedia.org/wiki/%E5%A0%86%E6%A0%88
            http://zh.wikipedia.org/wiki/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84
            http://student.zjzk.cn/course_ware/data_structure/web/zhanhuoduilie/zhanhuoduilie3.2.1.htm
            http://student.zjzk.cn/course_ware/data_structure/web/zhanhuoduilie/zhanhuoduilie3.1.1.htm
            http://student.zjzk.cn/course_ware/data_structure/web/main.htm

            posted @ 2011-05-26 00:48 unixfy 閱讀(139) | 評論 (0)編輯 收藏

            《深度探索 C++ 對象模型》讀書筆記——第一章 關于對象

            C++ 對象模型
            ·語言中直接支持面向對象程序設計的部分
            ·對于各種支持的底層實現機制

            virtual table

            理解底層實現模型的好處有
            ·寫出效率較高的代碼
            ·有更好的自信心


            關于對象
            布局、存取時間來自于
            ·virtual: virtual function, virtual base class
            ·derived class 與 base class 的轉換

            class data members: static, nonstatic
            class member functions: static, nonstatic, virtual

            1.簡單對象模型 Simple Object Model
            slots
            指向成員的指針

            2.表格驅動對象模型
            data member table
            member function table: slots

            Member Table 對象模型

            支持 virtual functions

            3.C++ 對象模型
            virtual table (vtbl)
            vptr: constructor, destructor, copy assignment

            type_info object for RTTI(運行時類型識別)

            優點:空間和存取時間的效率
            缺點:會導致重新編譯

            bptr

            (*px->vtbl[2])(px);
            (*px->vtbl[1])(px);
            _delete(px);

            vptr
            virtual table
            -----
            address -> type_info for X
            address -> X::~X()
            address -> X::foo()
            -----

            pt->vtbl[0]
            pt->vtbl[1]
            pt->vtbl[2]

            關鍵字所帶來的差異
            組合而非繼承是把 C 和 C++ 結合在一起的唯一可行方法
            conversion 運算符
            operator C_point()
            {
             return _c_point;
            }

            對象的差異
            C++ 程序設計模型直接支持三種程序設計典范 programming paradigms
            ·程序模型 procedural model
            ·抽象數據類型模型 abstract data type model
            ·面向對象模型 object-oriented model

            C++ 支持多態的方法
            ·隱含轉化 Shape* ps = new circle();
            ·virtual function ps->rotate();
            ·dynamic_cast, typeid
             if (Circle* pc = dynamic_cast<Circle*>(ps))
             {
             ...
             }

            class object 內存
            ·nonstatic data members
            ·alignment
            ·virutal(virtual functions, virtual base class)

            dynamic_cast<Base*>

            OB: object-based
            OO: object-oriented

            posted @ 2011-05-25 18:48 unixfy 閱讀(144) | 評論 (0)編輯 收藏
            僅列出標題
            共19頁: First 7 8 9 10 11 12 13 14 15 Last 
            久久天天躁狠狠躁夜夜网站| 久久久久亚洲AV无码永不| 久久精品国产精品青草app| 亚洲欧洲日产国码无码久久99| 香蕉久久夜色精品国产2020| 亚洲精品乱码久久久久久| 久久66热人妻偷产精品9| 无码乱码观看精品久久| 亚洲AV日韩精品久久久久久久| 亚洲国产精品无码久久久蜜芽 | 一本久久a久久精品综合夜夜| 久久中文字幕无码专区| 久久亚洲欧美国产精品 | 久久天堂AV综合合色蜜桃网| 成人资源影音先锋久久资源网| 亚洲精品无码久久毛片| 伊人久久免费视频| 亚洲愉拍99热成人精品热久久| 国产综合免费精品久久久| 色婷婷狠狠久久综合五月| 午夜天堂精品久久久久| 午夜精品久久影院蜜桃| 久久精品国产一区| 国产精品99精品久久免费| 亚洲七七久久精品中文国产| 国产精品一久久香蕉产线看| 亚洲精品美女久久久久99小说| 久久精品这里热有精品| 97精品国产97久久久久久免费| 中文字幕乱码久久午夜| 7777精品伊人久久久大香线蕉| 久久天天躁狠狠躁夜夜2020一| 国产精品九九久久免费视频 | 久久99精品久久久久久| 久久精品毛片免费观看| 欧洲精品久久久av无码电影| 亚洲欧美成人综合久久久| av色综合久久天堂av色综合在| 91麻豆国产精品91久久久| 国产精品99久久久久久宅男小说| 一本久道久久综合狠狠躁AV |