• <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://www.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都是非法的,但是不禁止復制,只是復制后改了也沒用的意思。  回復  更多評論
              

            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            友情連接

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            99久久精品国产一区二区| 亚洲精品午夜国产VA久久成人| 久久久久久国产a免费观看黄色大片 | 久久久久亚洲爆乳少妇无| 97久久精品人妻人人搡人人玩 | 精品国产一区二区三区久久蜜臀| 久久99国产综合精品免费| 一本色道久久88—综合亚洲精品| 久久天天躁狠狠躁夜夜avapp| 亚洲精品乱码久久久久久蜜桃| 亚洲乱码日产精品a级毛片久久| 99久久国产亚洲综合精品| 日韩电影久久久被窝网| 久久久国产亚洲精品| 国内精品人妻无码久久久影院导航| 精品国产乱码久久久久软件| 99蜜桃臀久久久欧美精品网站| 久久精品国产亚洲αv忘忧草 | 国产福利电影一区二区三区久久久久成人精品综合 | 久久久久亚洲精品无码蜜桃 | 久久久精品久久久久久| 久久免费视频一区| 欧洲性大片xxxxx久久久| 久久久一本精品99久久精品88| 久久久久亚洲AV成人片 | 国产精品激情综合久久| 久久久久久久综合日本| 亚洲综合伊人久久综合| 国产精品嫩草影院久久| 久久精品国产精品亚洲精品| 久久久久女人精品毛片| 久久精品国产亚洲AV不卡| 久久精品国产男包| 91超碰碰碰碰久久久久久综合| 一级a性色生活片久久无少妇一级婬片免费放| 中文无码久久精品| 久久99国产精品成人欧美| 久久久无码人妻精品无码| 一本大道久久香蕉成人网| 色综合久久中文色婷婷| 亚洲国产欧美国产综合久久|