• <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>
            OnTheWay2012
            埋葬昨天的我,迎來重生的我!
            posts - 15,  comments - 89,  trackbacks - 0

            http://m.shnenglu.com/Tveiker/archive/2011/01/08/138154.aspx本鏈接是“隨筆”寫的一篇名叫《鏈表實驗》的文章,以下是我的分析。

            我理解你說的學號的問題是:一個叫X是男性年齡是22歲的學生,假設其學號是2009000,把該學生加入到鏈表之后,該學生的
            學號發生了變化,不再是2009000。

            如果你所說的學號問題和上面的描述一致的話,該問題產生的原因是:Student類不應該有拷貝構造函數和賦值函數。
             假如為了實現Student類與STL容器搭配使用的能力(要獲得此種能力Student必須有拷貝構造函數和其他一些函數根據你所使用到的容器
             和算法所要求的特殊函數,例如operator<)的話,這兩個函數也應該換種寫法,為了實現此種能力這兩個函數有以下實現方法:
             (1)學號的轉移,參考STL的auto_ptr的控制權轉移策略

             以上是對你碰到問題的說明,另外從你所寫的代碼中還發現了一些問題和不足之處,具體詳述如下:
             問題
              (1)Student的構造函數(Student()、Student(char *name,char* sex,int age))沒有把next初始化
              (2)Student的拷貝構造函數沒有進行if (this != &s)的判斷
              (3)Student類中的Name、Sex可以不使用char*類型(之所以把這個情況說成是問題而不是不足之處是為了以后寫代碼是少犯與指針相關的錯誤)
              (4)在Student類的析構函數中不能對寫“Stu_no--;”這樣的語句,如果想實現學號重用的能夠的話就需要記錄學號的使用情況(本文不討論此問題)

             不足之處
              (1)形如class Student{
              的代碼風格不好,應該修改為
              class Student
              {
              (2)學號不應該是一個整數并且應該隱藏學號這一重要對象的生成方式(因為學號很可能每個學校不一樣,為了應對變化,所以對可能發生變化
                的地方進行封裝)
              (3)Student類不應該包含next指針
              (4)Link類中的Add函數的接口設計很不合理(在使用的時候需要先構造出一個Student,這很沒有必要)
              (5)Link類中的pivot作為類的成員變量不太合適并且沒有多大意義

            提醒你一下:請仔細思考拷貝構造函數的意義,拷貝構造的意義簡單來說就是克隆,而你寫的代碼沒有克隆好,所以的導致了學號問題
            針對上述所有問題的修改方案有三種
            (1)A方案:禁止拷貝構造
            (2)B方案:學號轉移 非法學號
            各個方案的實現方法如下,其中對于學號的生成方法這二種方案都一樣(為了簡單起見,學號仍然采用整數)

             1/************************************************************************/
             2/*                          學號生成                                    */
             3/************************************************************************/
             4
             5typedef int StudentID;
             6
             7class StudentIDGenerate
             8{
             9public:
            10    static StudentID GenerateID()
            11    {
            12        return StudentBaseID++;
            13    }

            14
            15private:
            16    static StudentID StudentBaseID;
            17}
            ;
            18
            19StudentID StudentIDGenerate::StudentBaseID = 2009000;
            20
            21/************************************************************************/
            22/*                            鏈表節點                                  */
            23/************************************************************************/
            24template <typename T>
            25struct LinkNode
            26{
            27    T m_value;
            28    LinkNode<T> *m_pNext;
            29
            30    LinkNode() : m_pNext(NULL)
            31    {
            32
            33    }

            34}
            ;
            以上是通用代碼,下面是方案A的代碼
              1/************************************************************************/
              2/*                       A方案                                          */
              3/************************************************************************/
              4
              5class Student
              6{
              7    friend class Link;
              8
              9public:
             10    Student();
             11    Student(string const &strName,string const &strSex, int nAge);
             12    ~Student();
             13
             14public:
             15    void display();
             16    void SetValue(string const &strName,string const &strSex, int nAge);
             17    int GetAge() const;
             18
             19private://通過把以下函數設置為私有來實現禁止拷貝構造的能力
             20    Student(const Student &);
             21    Student &operator=(const Student &s);
             22
             23private:
             24    string m_strName;
             25    int m_nAge;
             26    string m_strSex;
             27    StudentID m_ID;
             28}
            ;
             29
             30typedef LinkNode<Student> StudentNode;
             31
             32Student::Student()
             33{
             34    m_ID = StudentIDGenerate::GenerateID();
             35    m_nAge = 0;
             36}

             37
             38Student::Student(string const &strName,string const &strSex,int nAge)
             39{
             40    m_strName = strName;
             41    m_strSex = strSex;
             42    m_ID = StudentIDGenerate::GenerateID();
             43    m_nAge = nAge;
             44}

             45
             46Student::Student(const Student &s)
             47{
             48    assert(false);
             49}

             50
             51Student &Student::operator =(const Student &s)
             52{
             53    assert(false);
             54    return *this;
             55}

             56
             57Student::~Student()
             58{
             59    
             60}

             61
             62void Student::display() 
             63{
             64    cout<<"Name is:"<<m_strName<<"    ID is:"<<m_ID<<"    Sex is:"<<m_strSex<<"    Age is:"<<m_nAge<<endl;
             65}

             66
             67void Student::SetValue(string const &strName,string const &strSex, int nAge)
             68{
             69    m_strName = strName;
             70    m_strSex = strSex;
             71    m_nAge = nAge;
             72}

             73
             74int Student::GetAge() const
             75{
             76    return m_nAge;
             77}

             78
             79class Link
             80{
             81public:
             82    Link();
             83    ~Link();
             84
             85public:
             86    void Delete(StudentID);
             87    void Add(string const &strName,string const &strSex,int nAge);
             88    void Display();
             89
             90private:
             91    StudentNode *m_pHead;
             92    StudentNode *m_pTail;
             93}
            ;
             94
             95Link::Link()//構造空鏈表
             96{
             97    m_pHead=NULL;
             98    m_pTail=NULL;
             99}

            100
            101Link::~Link()//釋放內存
            102{
            103    while (NULL != m_pHead)
            104    {
            105        StudentNode *pTemp = m_pHead;
            106        m_pHead = m_pHead->m_pNext;
            107        delete pTemp;
            108    }

            109}
                
            110
            111void Link::Add(string const &strName,string const &strSex,int nAge)//向鏈表中添加學生
            112{
            113    if(m_pHead==NULL)
            114    {
            115        m_pHead = new StudentNode();
            116        m_pHead->m_value.SetValue(strName, strSex, nAge);
            117        m_pTail = m_pHead;
            118        m_pTail->m_pNext = NULL;
            119    }

            120    else
            121    {
            122        m_pTail->m_pNext = new StudentNode;
            123        m_pTail->m_pNext->m_value.SetValue(strName, strSex, nAge);
            124        m_pTail->m_pNext->m_pNext = NULL;
            125        m_pTail = m_pTail->m_pNext;
            126    }

            127}

            128
            129void Link::Display()//顯示鏈表中學生信息
            130{
            131    cout<<endl;
            132    StudentNode *pTemp = m_pHead;
            133    while (NULL != pTemp)
            134    {
            135        pTemp->m_value.display();
            136        pTemp = pTemp->m_pNext;
            137    }

            138    cout<<endl;
            139}

            140
            141void Link::Delete(int nAge)//刪除鏈表中所有年齡為nAge的學生
            142{
            143    StudentNode *pPre = m_pHead;
            144    StudentNode *pCur = m_pHead;
            145    while (NULL != pCur)
            146    {
            147        if (pCur->m_value.GetAge() == nAge)
            148        {
            149            if (pCur == m_pHead)
            150            {
            151                pPre = m_pHead = m_pHead->m_pNext;
            152            }

            153            else
            154            {
            155                pPre->m_pNext = pCur->m_pNext;
            156            }

            157            
            158            pCur->m_value.display();
            159            delete pCur;
            160            pCur = NULL != pPre ? pPre->m_pNext : NULL;
            161        }

            162        else
            163        {
            164            pPre = pCur;
            165            pCur = pCur->m_pNext;
            166        }

            167    }

            168}
            以下是測試方案A的代碼
            void main()
            {
                
            //測試零
                
            //vector<Student> vecStu;
                
            //Student st1;
                
            //vecStu.push_back(st1);

                
            //Student st2;
                
            //vecStu.push_back(st2);

                
            //測試一
                Link link;
                link.Add(
            "X","Boy",22);
                link.Add(
            "Y","Boy",20);
                link.Add(
            "Z","Boy",21);
                link.Add(
            "U","Girl",22);
                
                link.Display();
                link.Delete(
            21);
                
                link.Display();

                
            //測試二
                Link link1;
                link1.Add(
            "X","Boy",22);
                link1.Add(
            "Y","Boy",20);
                link1.Add(
            "Z1","Boy",21);
                link1.Add(
            "Z2","Boy",21);
                link1.Add(
            "U","Girl",22);

                link1.Display();
                link1.Delete(
            21);

                link1.Display();

                
            //測試三
                Link link2;
                link2.Add(
            "X","Boy",22);
                link2.Add(
            "Y","Boy",20);
                link2.Add(
            "Z1","Boy",21);
                link2.Add(
            "Z2","Boy",21);
                link2.Add(
            "U","Girl",22);

                link2.Display();
                link2.Delete(
            22);

                link2.Display();

                
            //測試四
                Link link3;
                link3.Add(
            "X","Boy",22);
                
                link3.Display();
                link3.Delete(
            22);

                link3.Display();

                
            //測試五
                Link link4;
                link4.Add(
            "X","Boy",22);
                link4.Add(
            "Y","Boy",20);
                link4.Add(
            "Z1","Boy",21);
                link4.Add(
            "Z2","Boy",21);
                link4.Add(
            "U","Girl",22);

                link4.Display();
                link4.Delete(
            1);

                link4.Display();
            }
            其中采用方案A是測試零下面所注釋掉的代碼不能通過編譯,在VC2008的IDE下會報:class“Student”: 沒有可用的復制構造函數或復制構造函數聲明為“explicit”錯誤

            為了修正此錯誤,對代碼就行了修改,也就是B方案
            const StudentID ErrorStudentID = 0;//其實非法學號是個范圍[負無窮,2009000]   添加的代碼
            mutable StudentID m_ID;//為了能夠在拷貝構造函數中修改該值,把其類型聲明為mutable  修改的代碼

            //修改的代碼
            Student::Student(const Student &s)
            {
                m_strName 
            = s.m_strName;
                m_strSex 
            = s.m_strSex;
                m_ID 
            = s.m_ID;
                s.m_ID 
            = ErrorStudentID;
                m_nAge 
            = s.m_nAge;
            }


            //修改的代碼
            Student &Student::operator =(const Student &s)
            {
                
            if (this != &s)
                
            {
                    m_strName 
            = s.m_strName;
                    m_strSex 
            = s.m_strSex;
                    m_ID 
            = s.m_ID;
                    s.m_ID 
            = ErrorStudentID;
                    m_nAge 
            = s.m_nAge;
                }


                
            return *this;
            }

            PS:
            使用面向對象語言進行程序設計的時候一個關鍵的問題是:設計一個好的類,這里的Student類就是一個典型的例子。
            學習的時候當然可以自己寫個鏈表,自己管理內存;但是在實際工作中還是要多用STL現成的容器和算法,只有這樣才能提高代碼的質量,降低錯誤發生的概率。
            上面代碼實際還可以繼續進行改進,不夠寫道此種程度基本上沒有什么大問題了。
            posted on 2011-01-09 07:45 OnTheWay 閱讀(1617) 評論(2)  編輯 收藏 引用 所屬分類: 個人感悟

            FeedBack:
            # re: 對“隨筆”所寫的一篇文章《鏈表實驗》的一點看法
            2011-01-09 11:17 | あ維wêiセ
            謝謝咯,呵呵。我喜歡這代碼風格,向你學習  回復  更多評論
              
            # re: 對“隨筆”所寫的一篇文章《鏈表實驗》的一點看法
            2011-01-09 19:58 | 陳梓瀚(vczh)
            我認為問題只需要修改成,只將某一個指定的vector<Student>里面的Student實例視為合法實例就好了。其他地方存放的Student都是非法的,但是不禁止復制,只是復制后改了也沒用的意思。  回復  更多評論
              

            <2011年1月>
            2627282930311
            2345678
            9101112131415
            16171819202122
            23242526272829
            303112345

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            友情連接

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            无码8090精品久久一区| 久久久免费精品re6| 亚洲伊人久久大香线蕉综合图片| 人妻无码αv中文字幕久久| A级毛片无码久久精品免费| 亚洲中文字幕无码久久2020| 国产亚州精品女人久久久久久| 久久九九兔免费精品6| 久久福利片| 久久精品人人做人人妻人人玩| 久久久91人妻无码精品蜜桃HD| 久久精品国产亚洲AV麻豆网站| 精品久久久久久无码不卡| 国内精品久久久久久野外| 久久精品中文字幕一区| 久久青青草原亚洲av无码| 激情伊人五月天久久综合| 无码八A片人妻少妇久久| 狠狠色伊人久久精品综合网| .精品久久久麻豆国产精品| 无码国内精品久久综合88| 欧美久久一级内射wwwwww.| 97久久精品国产精品青草| 色婷婷综合久久久中文字幕 | 国产综合成人久久大片91| 欧美黑人激情性久久| 久久九九久精品国产免费直播| 亚洲精品无码久久久| 久久国产视屏| 国产精品美女久久久久AV福利| 久久这里只有精品久久| 91精品国产综合久久精品| 久久综合给合久久狠狠狠97色| 久久久久波多野结衣高潮| 久久久亚洲AV波多野结衣| 亚洲性久久久影院| 亚洲午夜无码AV毛片久久| 久久久久久久波多野结衣高潮| 久久精品国产99久久久古代| 精品综合久久久久久98| 97久久婷婷五月综合色d啪蜜芽 |