• <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>

            第二桶 基于對(duì)象的編程 第三碗 老C首演迭代模式 小P決定深練內(nèi)功

                 “感覺(jué)這一家有做大的趨勢(shì)……”老C一邊喝茶消食一邊對(duì)小P發(fā)表自己的看法。
                 “的確,他家已經(jīng)把旁邊的店生意快搶光了,估計(jì)過(guò)一些時(shí)間就會(huì)把隔壁的店買下來(lái)了。”小P亦有同感,“怪不得最近食堂的刀削面師傅辭工,可能創(chuàng)業(yè)去了……”
                 “?是么?呵呵,也許吧。”老C笑道,“不過(guò)看在你請(qǐng)客的面子上,我決定和你多聊幾句……”
                 “哦,是的是的。你要告訴我如何更好的實(shí)現(xiàn)線性表。”小P接道。
                 “嘻嘻,是的是的。不過(guò)這次我要先寫一段代碼……”老C說(shuō)道。
                 “……是啊……”小P于是很自覺(jué)的將白板擦干凈,并拉到兩人面前。
                 “我們現(xiàn)在的題目是,寫一個(gè)函數(shù),作用是在一個(gè)線性表中查找某一個(gè)特定元素。”老C說(shuō)道,“我們先從數(shù)組開(kāi)始,這樣比較簡(jiǎn)單。”


            int* find (int* first, int* last, const int val);

            int* find(int* first, int* last, const int val)
            {
                for (; first != last; ++first)
                {
                    if (val == *first)
                    {
                        break;
                    }
                }

                return first;
            }

                 “在這里我們用[first, last)表示需要查找的區(qū)間,如果找到就返回元素的指針,否則返回last。”老C解釋,“為了更清楚的表明此函數(shù)所在的應(yīng)用環(huán)
            境,我們?cè)賮?lái)一段使用它的代碼。”

            #include <iostream>

            int* find (int* first, int* last, const int val);

            const int MAX_SIZE = 5;

            int main()
            {
                int a[MAX_SIZE] = {0, 1, 2, 3, 4};

                const int* iter = find(&a[0], &a[MAX_SIZE], 3);

                if (iter != &a[MAX_SIZE])
                {
                    std::cout << "The element is at NO. " << (iter - &a[0]) + 1 << " position." << std::endl;
                }
                else
                {
                    std::cout << "Not be found!" << std::endl;
                }
            }


            int* find(int* first, int* last, const int val)
            {
                for (; first != last; ++first)
                {
                    if (val == *first)
                    {
                        break;
                    }
                }

                return first;
            }

                 “看,find()函數(shù)就是這樣被使用的。”老C說(shuō)道,“同時(shí)我要提醒一下你,數(shù)組類型與指針類型是不同的類型,因?yàn)閿?shù)組類型還帶有數(shù)組長(zhǎng)度的信息。比如 int a[2] 與 int* a,這是兩種類型,其中int a[]可以被內(nèi)部轉(zhuǎn)型為int* ,但是反之則不行。可惜的是數(shù)組類型無(wú)法作為函數(shù)參數(shù),在使用函數(shù)對(duì)數(shù)組進(jìn)行操作的時(shí)候不得不將其轉(zhuǎn)型為指針……這個(gè)就是C中的數(shù)組降維問(wèn)題……總之你要 明白,數(shù)組與指針是不同的類型,但數(shù)組可以被轉(zhuǎn)型為指針——代價(jià)是丟失長(zhǎng)度信息——反之則不行。”
                 “好,我了解了。”小P回答,心想好像在哪本書上說(shuō)過(guò)貌似數(shù)組和指針沒(méi)有什么區(qū)別的。為了確認(rèn)這個(gè)事情,他決定再google一下。
                 “喏,如果我們使用了[first, last)的表達(dá)形式,很多對(duì)線性表的操作就可以統(tǒng)一起來(lái),這樣我們將指向線性表元素的指針提取出來(lái),就使得用戶使用這些線性表就好像在使用一個(gè)數(shù)組似 的。這樣會(huì)大大減輕用戶記憶的難度,同時(shí)也使得編程人員避免了很多下意識(shí)的錯(cuò)誤——比如過(guò)一錯(cuò)誤。”老C說(shuō)道,“而這個(gè)被提煉出來(lái)的指針,我們就叫它 iterator。”
                 “是么?”小P道,“原來(lái)iterator就是這樣來(lái)的啊。”
                 “剛才的例子是trivial的,我們?cè)偕钊胍稽c(diǎn)點(diǎn)。”老C說(shuō)道,“如果我們希望find()函數(shù)可以被運(yùn)用到所有類型的線性表,那么可以怎么做呢?”看 到小P有些槑,老C自問(wèn)自答,“其實(shí)方法有很多,我們可以將find()看成對(duì)象——一切皆為對(duì)象——如果使用面向?qū)ο蟮姆椒ǎ缓筇釤挸鲆粋€(gè)find 類,讓findVector和findList成為它的子類,find類中的操作寫為虛函數(shù),然后讓findVector子類和findList子類去修 改這些虛函數(shù)以滿足自己的實(shí)際需要,這可以被稱為strategy模式的一個(gè)簡(jiǎn)單應(yīng)用。但是這個(gè)方法我們先避開(kāi)不談,在這里我們采用另外一個(gè)方法。”他找 到茶杯喝了一口,“我們將這個(gè)iterator提煉為一個(gè)類,同時(shí)保持find()函數(shù)的實(shí)現(xiàn)不變,然后在這個(gè)iterator上動(dòng)腦筋。”
                 “那么應(yīng)當(dāng)怎么做呢?”小P問(wèn)道。
                 “嗯,如果find()函數(shù)的代碼不變,那么我們可以這么做。”老C說(shuō)著打開(kāi)了電腦,新建立了一個(gè)工程開(kāi)始敲鍵盤,一邊敲一邊給小P解釋著。

            find.h:

            #if !defined(FIND_H_)
            #define FIND_H_

            #include "iterator.h"

            Iterator& find(Iterator& first, Iterator& last, const ValueType& val)
            {
                for (; first != last; ++first)
                {
                    if (val == *first)
                    {
                        break;
                    }
                }

                return first;
            }

            #endif // FIND_H_

                 “看,我們希望的finde()函數(shù)可以是這樣的一種接口和實(shí)現(xiàn)。”老C解釋,“而且希望它可以這樣被使用。”

            main.cpp:

            #include "implement.h"
            #include "find.h"

            #include <iostream>

            const int MAX_SIZE = 5;

            int main()
            {
                IntValueType a[MAX_SIZE] = {0, 1, 2, 3, 4};

                IntVector intVec(&a[0], &a[MAX_SIZE]);
                IntList intList(&a[0], &a[MAX_SIZE]);

                //IntVectorIter first = intVec.begin();
                //IntVectorIter last = intVec.end();

                IntListIter first = intList.begin();
                IntListIter last = intList.end();

                Iterator& it = find(first, last, IntValueType(4));

                if (it != last)
                {
                    std::cout << "Find " << (*it) << std::endl;
                }
                else
                {
                    std::cout << "Cannot find " << std::endl;
                }    

                return 0;
            }

                 “在這里我們假設(shè)find()函數(shù)即可以用在vector上,也可以用在linked list上,橋梁就是Iterator類。”老C解釋道,“這下我們就可以根據(jù)find()函數(shù)的實(shí)現(xiàn)看看我們需要什么樣子的Iterator類的接口了。”

            class Iterator
            {
            public:
                virtual Iterator& operator++() = 0;

                virtual ValueType& operator*() = 0;

                virtual bool operator==(Iterator& rhs) = 0;

                virtual bool operator!=(Iterator& rhs) = 0;

            protected:
                ~Iterator() {}
            };

                 “根據(jù)find()函數(shù)的實(shí)現(xiàn),我們知道Iteratro類必須擁有上面列出的接口。在這里我把Iterator類設(shè)計(jì)為抽象類,因?yàn)樗皇翘峁┮粋€(gè)接口規(guī)范而已。”老C解釋。
                 “那么為什么它的析構(gòu)函數(shù)是protected的呢?”小P問(wèn)。
                 “哦,這是一個(gè)習(xí)慣用法。一般的抽象類的析構(gòu)函數(shù)要么是public virtual的,要么是protected 非virtual的。我在這里將它設(shè)計(jì)為protected 非virtual是因?yàn)槲也幌胱孖terator動(dòng)態(tài)生成,就是說(shuō)不希望Iterator的繼承類的對(duì)象是在堆上創(chuàng)建的。”看到小P還是有些莫名其妙,老 C接著說(shuō),“關(guān)于這個(gè)小技巧,我會(huì)在后面一段時(shí)間……一個(gè)月后吧……跟一些其他的小技巧一起總結(jié)一下,在這里你就先將就著看吧。”
                 “也好……”小P槑。
                 “接下來(lái)的代碼……很傻很天真……”老C解釋道,“因?yàn)樵谶@里只是說(shuō)明問(wèn)題而已,你可不要學(xué)習(xí)這種設(shè)計(jì)啊。”

            class ValueType
            {
                friend std::ostream& operator<<(std::ostream& os, const ValueType& value);
            public:
                virtual ~ValueType() {}

                virtual bool operator==(const ValueType& rhs) const = 0;

                virtual void print(std::ostream& os) const = 0;
            };

            std:: ostream& operator<<(std::ostream& os, const ValueType& valueType)
            {
                valueType.print(os);

                return os;
            }

                 “因?yàn)槲覀儧](méi)有辦法在系統(tǒng)定義類型——比如int——與用戶定義類型——比如Student——間保持一致,而我們又希望對(duì)于int數(shù)組和Student 數(shù)組都可以使用find()函數(shù)……不得以,我設(shè)計(jì)了一個(gè)叫做ValueType的傻傻基類,并將int用IntValueType類包裹了一下,使得類 似int這種系統(tǒng)定義類型也可以加入到我們的組織當(dāng)中。”老C解釋,“為了便于屏幕輸出,我還重載了ostream的輸出函數(shù)。”他撓撓頭,“最后我又畫 蛇添足的寫了一個(gè)Container的基類,用于存放我們的數(shù)據(jù)結(jié)構(gòu)。其實(shí)它什么也沒(méi)有做,只是為了統(tǒng)一下類型而已。”

            class Container
            {
            public:
                virtual ~Container() {}
            };

                 “最后我們把這些接口放入一個(gè)文件當(dāng)中。”老C新建了一個(gè)頭文件,將類的定義放入其中。

            iterator.h:

            #if !defined(ITERATOR_H_)
            #define ITERATOR_H_

            #include <iostream>


            class Iterator;
            class Container;
            class ValueType;

            //////////////////////////////////////////////////////////////////////////
            // Base classes.
            //
            class Iterator
            {
            public:
                virtual Iterator& operator++() = 0;

                virtual ValueType& operator*() = 0;

                virtual bool operator==(Iterator& rhs) = 0;

                virtual bool operator!=(Iterator& rhs) = 0;

            protected:
                ~Iterator() {}
            };

            class Container
            {
            public:
                virtual ~Container() {}
            };

            class ValueType
            {
                friend std::ostream& operator<<(std::ostream& os, const ValueType& value);
            public:
                virtual ~ValueType() {}

                virtual bool operator==(const ValueType& rhs) const = 0;

                virtual void print(std::ostream& os) const = 0;
            };

            std:: ostream& operator<<(std::ostream& os, const ValueType& valueType)
            {
                valueType.print(os);

                return os;
            }


            #endif // ITERATOR_H_

                 “下來(lái)又是一些天真的實(shí)現(xiàn)代碼,”老C不好意思的撓頭,“就先作為說(shuō)明示例代碼吧,等我們掌握了更多的知識(shí)后再來(lái)修改這些代碼吧。”

            implement.h:

            #if !defined(IMPL_H_)
            #define IMPL_H_

            #include "iterator.h"

            #include <cassert>
            #include <typeinfo>

            //////////////////////////////////////////////////////////////////////////
            // Derived classes.
            //
            // IntVector.
            //
            class IntValueType : public ValueType
            {    
            public:
                IntValueType(int content = 0) : content_(content) {}

                virtual bool operator==(const ValueType& rhs) const
                {
                    try
                    {
                        const IntValueType& intValue = dynamic_cast<const IntValueType&>(rhs);    
                        return content_ == intValue.content_;
                    }
                    catch (std::bad_cast e)
                    {
                        std::cout << "Bad cast, this object is not of type IntValue! " << std::endl;
                        return false;
                    }        
                }

                virtual void print(std::ostream& os) const
                {
                    os << content_;
                }

            private:
                int content_;
            };


            class IntVectorIter : public Iterator
            {
            public:
                IntVectorIter(IntValueType* ptr = 0) : ptr_(ptr) {}

                virtual Iterator& operator++()
                {
                    ++ptr_;

                    return *this;
                }

                virtual ValueType& operator*()
                {
                    return *ptr_;
                }

                virtual bool operator==(Iterator& rhs)
                {
                    try
                    {
                        IntVectorIter& intIter = dynamic_cast<IntVectorIter&>(rhs);
                        return ptr_ == intIter.ptr_;
                    }
                    catch (std::bad_cast e)
                    {
                        std::cout << "Bad cast, this object is not of type IntVectorIter! " << std::endl;
                        return false;
                    }
                }

                virtual bool operator!=(Iterator& rhs)
                {
                    return !(operator==(rhs));
                }

            private:
                IntValueType* ptr_;

            };

            class IntVector : public Container
            {
            public:
                IntVector(IntValueType* first, IntValueType* last)
                    : size_(0), array_(0)
                {
                    size_ = last - first;
                    assert(size_ > 0);

                    array_ = new IntValueType[size_];

                    for (size_t i = 0; i < size_; ++i)
                    {
                        *(array_ + i) = *(first + i);
                    }
                }

                ~IntVector()
                {
                    if (array_)
                    {
                        delete[] array_;
                        array_ = 0;
                    }
                    size_ = 0;
                }

                virtual IntValueType* begin()
                {
                    return &array_[0];
                }

                virtual IntValueType* end()
                {
                    return &array_[size_];
                }

            private:
                size_t    size_;
                IntValueType*    array_;
            };

            //
            // IntList
            //

            struct IntNode
            {
                IntNode* prev_;
                IntNode* next_;

                IntValueType content_;
            };

            class IntListIter : public Iterator
            {
            public:
                IntListIter(IntNode* intNode = 0) : nodePtr_(intNode) {}

                virtual Iterator& operator++()
                {
                    nodePtr_ = nodePtr_->next_;

                    return *this;
                }

                virtual ValueType& operator*()
                {
                    return nodePtr_->content_;
                }

                virtual bool operator==(Iterator& rhs)
                {
                    try
                    {
                        IntListIter& it = dynamic_cast<IntListIter&>(rhs);
                        return nodePtr_ == it.nodePtr_;
                    }
                    catch (std::bad_cast e)
                    {
                        std::cout << "Bad cast, this object is not of type IntListIter! " << std::endl;
                        return false;
                    }
                }

                virtual bool operator!=(Iterator& rhs)
                {
                    return !(operator==(rhs));
                }

            private:
                IntNode* nodePtr_;
            };

            class IntList : public Container
            {
            public:
                IntList(IntValueType* first, IntValueType* last)
                    : size_(0), list_(0)
                {
                    size_ = last - first;
                    assert(size_ > 0);

                    list_ = new IntNode;        
                    list_->prev_ = list_;
                    list_->next_ = list_;

                    for (size_t i = 0; i < size_; ++i)
                    {
                        IntNode* newNode = new IntNode;
                        newNode->content_ = *(first + i);
                        newNode->next_ = list_;
                        newNode->prev_ = list_->prev_;
                        newNode->prev_->next_ = newNode;
                        newNode->next_->prev_ = newNode;
                    }
                }

                ~IntList()
                {
                    while (list_->next_ != list_)
                    {
                        IntNode* it = list_->next_;
                        it->prev_->next_ = it->next_;
                        it->next_->prev_ = it->prev_;

                        it->prev_ = 0;
                        it->next_ = 0;
                        it->content_ = 0;
                        delete it;
                        it = 0;
                    }

                    list_->prev_ = 0;
                    list_->next_ = 0;
                    delete list_;
                    list_ = 0;
                    size_ = 0;
                }

                virtual IntNode* begin()
                {
                    return list_->next_;
                }

                virtual IntNode* end()
                {
                    return list_;
                }

            private:
                size_t     size_;
                IntNode* list_;
            };



            #endif // IMPL_H_

                 “因?yàn)椴幌攵鄤?dòng)腦筋,所以代碼中充滿了轉(zhuǎn)型,這些都是不良的設(shè)計(jì)。你大概明白一下iterator模式的思想就可以了,以后我們還會(huì)優(yōu)化這些代碼的。”老C說(shuō)道,“不用太關(guān)注代碼的細(xì)節(jié),只要知道我們通過(guò)運(yùn)算符重載保證了用戶代碼的簡(jiǎn)單明了就達(dá)到目的了。”
                 “唔,我看看先……”小P回答。他問(wèn)了幾個(gè)代碼中的問(wèn)題,想了想,說(shuō),“看來(lái)iterator模式就是將對(duì)container中元素的操作與container本身分開(kāi),這樣就可以達(dá)到復(fù)用某些算法的目的?”
                 “呵呵,差不多就是這樣啦。”老C回答,“要看懂這些古怪的代碼,還有一些細(xì)節(jié)需要了解,但是我們不要過(guò)于糾纏到細(xì)節(jié)當(dāng)中,先從整體上把握一下就可以了。 這些細(xì)節(jié)問(wèn)題,當(dāng)然需要重視,但是不是現(xiàn)在。等我們接觸的代碼再多一些,我們?cè)倩仡^看看這些細(xì)節(jié)問(wèn)題吧。”他揉揉手指,“看,這下find()函數(shù)即可以 在vector上使用,也可以在list上使用了吧;而且對(duì)于container數(shù)據(jù)的操作也方便了一些。代價(jià)是我們?cè)谀缓箅s七雜八的搞了一些小動(dòng)作。” 老C伸了一個(gè)懶腰,“等我們掌握了足夠的細(xì)節(jié),再回來(lái)修改這些代碼吧,先用面向?qū)ο蟮姆椒ǎ儆媚0宓姆椒ā贿^(guò)現(xiàn)在談?wù)撨@些兒還太早,有害無(wú)益,我們 還是先不要太激進(jìn)的好。”
                 “哦?好吧,”小P覺(jué)得自己越來(lái)越好奇了,“還有面向?qū)ο蠛湍0宓姆椒ò。?#8221;
                 “是啊是啊,這些我們以后慢慢說(shuō)……”老C心想一次都搞光了,以后晚飯就沒(méi)有人請(qǐng)客了。
                 “呵呵,好啊好啊。不過(guò)這些代碼我還是要再看看,你給我傳一下吧……”小P道。
                 “唉,現(xiàn)在不要糾纏在這些代碼上啦,我們還是要平衡一下……”老C回答,“不過(guò)我還是把這些代碼放到服務(wù)器上,你用ftp下載吧。”
                 “好啊,”小P道,“你說(shuō)不用糾纏在這些代碼的細(xì)節(jié)上,那么接下來(lái)我們要討論一些什么內(nèi)容呢?”
                 “……”老C深沉了一會(huì),“接下來(lái)我們要討論——數(shù)學(xué)。”
                 “數(shù)學(xué)?”小P奇道。
                 “唔,”老C點(diǎn)頭,“我們編碼就像練功,語(yǔ)言啊,代碼結(jié)構(gòu)啊,風(fēng)格啊什么的就是外功;而解決問(wèn)題的方法就是內(nèi)功——內(nèi)功需要一定的專業(yè)知識(shí)和數(shù)學(xué)功底。無(wú) 論內(nèi)外功都是要修煉的……否則哪怕你程序的結(jié)構(gòu)再好,風(fēng)格再優(yōu)美,但是你無(wú)法解決稍微復(fù)雜一些的實(shí)際問(wèn)題——那么一切也是白搭。”
                 “是啊,也對(duì)。”小P贊同。“那么需要討論些什么內(nèi)容呢?”
                 “呵呵,也不會(huì)很復(fù)雜,只是一些基本的分析問(wèn)題,解決問(wèn)題的基本思路而已。”老C說(shuō)道,“你的數(shù)學(xué)還是不錯(cuò)的,等到融會(huì)貫通了,對(duì)你來(lái)說(shuō)小菜而已。”老C 想想,“其實(shí)不僅僅是數(shù)學(xué),我們還可以順便討論一些信號(hào)、電路和自控方面的問(wèn)題。因?yàn)榫幊桃欢ㄒ陧?xiàng)目中進(jìn)行,在項(xiàng)目中學(xué)習(xí)得是最快的。等到掌握的知識(shí)細(xì) 節(jié)足夠豐富的時(shí)候,我想我們可以開(kāi)始做一些小工程了。”
                 “好啊,沒(méi)有問(wèn)題!”小P點(diǎn)頭。
                 “但是我們?cè)陂_(kāi)始小的工程之前先要簡(jiǎn)單的討論一下遞歸和有限狀態(tài)機(jī)。”老C說(shuō),“這些東東用C++的基于對(duì)象的部分完全可以應(yīng)付。不過(guò)……”他打了一個(gè)哈欠。
                 “嗯,時(shí)候也不早了,我們還是先閃人吧!”小P拾趣的說(shuō)道。
                 兩個(gè)人跑到隔壁,叫上大部隊(duì),一邊談?wù)撟罱陌素允录贿呄虼箝T晃去……

            (遞歸?和遞推公式有關(guān)嗎?)


            posted on 2009-03-11 02:59 Anderson 閱讀(1341) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            <2009年3月>
            22232425262728
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(6)

            隨筆檔案(21)

            文章檔案(1)

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            欧美久久天天综合香蕉伊| 久久精品国产亚洲AV忘忧草18| 久久久国产99久久国产一| 久久久噜噜噜久久| 久久精品无码一区二区WWW| 亚洲AV无码久久精品成人| 国产精品久久久久久影院| 久久国产成人午夜aⅴ影院| 国产香蕉久久精品综合网| 久久亚洲国产成人精品性色| 国产精品久久久久乳精品爆 | 久久综合久久美利坚合众国| 精品无码久久久久久尤物| 久久精品无码免费不卡| 国内精品久久久久伊人av| 日本久久中文字幕| 精品综合久久久久久97超人 | 精品久久久久中文字幕一区| 久久精品中文无码资源站| 中文精品久久久久国产网址| 久久久久se色偷偷亚洲精品av| 狠狠人妻久久久久久综合蜜桃| 亚洲精品乱码久久久久久蜜桃图片| 亚洲综合久久综合激情久久| 奇米影视7777久久精品| 久久SE精品一区二区| 欧美色综合久久久久久| 国产午夜精品久久久久九九| 国产精品99久久免费观看| 亚洲乱码精品久久久久..| 久久天天躁夜夜躁狠狠躁2022 | 久久人人妻人人爽人人爽| 久久综合视频网| 久久亚洲AV无码精品色午夜麻豆| 久久精品成人免费观看97| 草草久久久无码国产专区| 国产激情久久久久影院老熟女| 久久成人精品视频| 精品免费tv久久久久久久| 国产真实乱对白精彩久久| 久久久久久毛片免费看|