乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      操作符重載

       pgj555 2014-01-16

       




       


      重載不能改變操作符的優(yōu)先級


       


      如果一個內(nèi)建操作符是一元的,那么所有對它的重載仍是一元的。如果是二元的重載后也是二元的


       


       下面看一個有代表性的例子::


      頭文件Complex.h:


      #include <iostream>
      using namespace std;


      class Complex {
      public:
         Complex();
         Complex(double);
         Complex(double,double);


         void write() const;
         Complex operator +(const Complex &) const;
         Complex operator -(const Complex &) const;
         Complex operator *(const Complex &) const;
         Complex operator /(const Complex &) const;
      private:
         double real;
         double imag;
      };


      Complex::Complex(){
         real = imag = 0.0;
      }


      Complex::Complex(double re) {
         real = re;
         imag = 0.0;
      };


      Complex::Complex(double re,double im) {
         real = re;
         imag = im;
      }


      void Complex::write() const {
         cout << real << " + " << imag << 'i';
      };


      Complex Complex::operator + (const Complex &u) const {
         Complex v(real+u.real,imag+u.imag);
         return v;
      }


      Complex Complex::operator - (const Complex &u) const {
         Complex v(real-u.real,imag-u.imag);
         return v;
      }


      Complex Complex::operator* (const Complex &u) const {
         Complex v(real * u.real - imag * u.imag,real * u.imag + imag * u.real);
         return v;
      }


      Complex Complex::operator / (const Complex &u) const {
         double temp = u.real * u.real + u.imag * u.imag;
         Complex v( (real * u.real + imag * u.imag ) / temp, ( imag * u.real - real * u.imag ) / temp);
         return v;
      }


       


      測試文件:Complex.cpp和測試結(jié)果:



       


      一個被重載的操作符,就是一個用戶自定義的函數(shù),只不過它可以享受操作符語法所帶來的便利


       


      除了內(nèi)存管理操作符new、new[]、delete、delete[]之外,一個以頂層函數(shù)形式被重載的操作符必須在它的參數(shù)列表中包含一個類的對象


      下標(biāo)操作符[]、賦值操作符=、函數(shù)調(diào)用操作符()和指針操作符->必須以類成員函數(shù)的形式進(jìn)行重載(這樣可以保證第一個操作數(shù)是類的對象,不然9[x]、6.32=x,不被接受)


      操作符(如%)要么以成員函數(shù)被重載,要么以頂層函數(shù)被重載。對于后者將至少帶一個對象參數(shù),這是因為操作符以頂層函數(shù)實現(xiàn)時,如果連一個參數(shù)都沒有,那么對如下表達(dá)式   x % y  編譯系統(tǒng)就不能區(qū)分%是內(nèi)建的,還是用戶的。如果操作符%是類成員函數(shù),或是有一個類對象參數(shù)的頂層函數(shù),編譯系統(tǒng)就能夠根據(jù)特定的上下文決定調(diào)用哪一個%操作符


       


      頂層函數(shù)重載操作符,類名和域解析符都沒有了,因為它不是一個類成員函數(shù)


       


      被重載的操作符,要么是一個類成員函數(shù),要么在它的參數(shù)列表中包含一個類成員!!


       


      下標(biāo)操作符[]和函數(shù)調(diào)用操作符()只能以成員函數(shù)的形式被重載,不能成為頂層函數(shù)!!


      eg:



       


      修正后:



       


      在上面那種情況,如果想要第二個表達(dá)式成功的話,就需要定義一個頂層函數(shù)重載+了


       


      有一點(diǎn)要明白,當(dāng)定義頂層函數(shù)時,函數(shù)里面不能含有對象的私有成員操作,否則編譯通不過,下面有三種方法可以解決:


      1,將私有成員設(shè)計為public成員,但是這種方法違背了類的信息隱藏原則


      2,在Complex中加入用于訪問real和imag的公有成員函數(shù),但是容易造成接口混淆


      3,將操作符重載函數(shù)聲明為類的friend,但是不符合面向?qū)ο笤瓌t,應(yīng)少用,建議僅在操作符重載時使用


       


      類的私有成員只能被該類的成員函數(shù)和該類的friend函數(shù)訪問


      類的保護(hù)成員只能被該類的或其派生類的成員函數(shù)和該類的friend函數(shù)訪問


       


      class C {


           //....


        friend int f();


        //...


      };


      該聲明賦予f訪問C的私有和保護(hù)成員的權(quán)力,因為f不是成員函數(shù),該聲明可以放在C中的private、protected或public的任意部分,不受訪問控制符的影響、限制


       


      程序員可對操作符>>進(jìn)行重載,以支持用戶自定義數(shù)據(jù)類型。>>的第一個操作數(shù)是系統(tǒng)類的對象(如cin是系統(tǒng)類istream的對象),而這些重載函數(shù)時以類成員函數(shù)的形式實現(xiàn)的。


      如果在對用戶自定義的類型重載>>時,就必須對系統(tǒng)類的源代碼進(jìn)行修改,而這顯然是非常不明智的做法,因此只能將>>重載函數(shù)設(shè)計為頂層函數(shù)


       


      輸入流對象總是以引用方式傳遞,這是因為系統(tǒng)為了接受輸入數(shù)據(jù),需要更新輸入流對象的某些信息


      如果被重載>>的函數(shù)中和類的私有數(shù)據(jù)或者保護(hù)數(shù)據(jù)打交道,則需要將重載操作符聲明為friend


       


      拷貝構(gòu)造函數(shù)和賦值操作符(=),都是用來拷貝一個類的對象給另一個相同類型的對象。


      拷貝構(gòu)造函數(shù)將一個對象拷貝到另一個新的對象(因為拷貝-構(gòu)造);賦值操作符將一個對象拷貝到另一個已經(jīng)存在的對象


       


      如果類的作者沒有提供拷貝構(gòu)造函數(shù),也沒有重載賦值操作符,編譯器將會給這個類提供一個拷貝構(gòu)造函數(shù)和一個賦值操作符。編譯器提供的拷貝構(gòu)造函數(shù)和賦值操作符的運(yùn)轉(zhuǎn)機(jī)制是:將源對象中的每個數(shù)據(jù)成員拷貝到目標(biāo)對象相應(yīng)的數(shù)據(jù)成員中


       



       


      看例子:



       


      如果類的作者定義了指針成員,且該指針指向一塊動態(tài)分配的存儲空間,就應(yīng)該為這個類設(shè)計拷貝構(gòu)造函數(shù),并重載賦值操作符


      注意不要返回臨時變量,重載里面錯綜復(fù)雜,小心一點(diǎn)


       


      下標(biāo)操作符[]必須要以成員函數(shù)的形式進(jìn)行重載!


       class C {         //可以修改對象


      returntype & operator[] (paramtype);


      };


      或者:


      class C {            //不能修改對象


      const returntypr & operator[] (paramtype) const;


      };


      例子:


      頭文件:test.h



       


      測試文件和結(jié)果:



       


      上面可以不提供const版本的重載,但是就不能處理非const的對象,所以,有時候要考慮這一點(diǎn),加上const重載!


       


       


      函數(shù)調(diào)用操作符()必須要以成員函數(shù)的形式重載。


      class C {


      returntype operator()(paramtypes);


      };


       


      看例子:


      頭文件inttwoarray.h


      #include <iostream>
      #include <string>
      using namespace std;


      class intTwoArray {
      public:
         int & operator()(int,int);
         const int & operator() (int,int) const;
         intTwoArray(int,int);
         int get_size1() const { return size1; }
         int get_size2() const { return size2; }
      private:
         int size1;
         int size2;
         int *a;
      };


      int & intTwoArray::operator() (int i,int j) {
         if( i < 0 || i >= size1 )
            throw string("FirstOutOfBounds");
         if( j < 0 || j >= size2 )
            throw string("SecondOutOfBounds");
         return a[i * size2 + j];
      }


      const int & intTwoArray::operator() (int i,int j) const {
         if(i < 0 || i >= size1)
            throw  string("FirstOutOfBounds");
         if(j < 0 || j >= size2)
            throw string("SecondOutOfBounds");
         return a[i * size2 + j];
      }


      intTwoArray::intTwoArray(int s1,int s2) {
         int size = s1 * s2;
         try{
            a = new int[size];
         }
         catch(bad_alloc) {
            cerr << "Can't allocate storage for intTwoArray\n";
            throw;
         }
         size1 = s1;
         size2 = s2;
      }


      測試程序和結(jié)果:



       


      自增,自減也可以重載,但是前置,后置一共四種,前后置通過一個int參數(shù)區(qū)分,但是這個參數(shù)沒有什么實際用途,僅僅起到區(qū)分的作用


      例子:


       頭文件clock.h         (需要注意一點(diǎn),這個地方注意注釋部分中間的代碼,一定要加上否則。。。。。)


      #include <iostream>
      #include <iomanip>
      using namespace std;


      //**********************************************************
      class Clock;
      ostream & operator << (ostream &,const Clock &);
      //**********************************************************


      class Clock {
      public:
       Clock(int = 12,int = 0 ,int = 0 );
       Clock tick();
       friend ostream & operator << (ostream &,const Clock &);
       Clock operator++();
       Clock operator++(int);
      private:
       int hour;
       int min;
       int ap;
      };


      Clock::Clock(int h,int m,int ap_flag) {
       hour = h;
       min = m ;
       ap = ap_flag;
      }


      Clock Clock::tick() {
       ++ min;
       if( min == 60) {
        hour ++;
        min = 0;
       }
       if(hour == 13)
        hour = 1;
       if(hour == 12 && min == 0)
        ap = !ap;
       return *this;
      }


      Clock Clock::operator++() {
       return tick();
      }


      Clock Clock::operator++(int n) {
       Clock c = *this;
       tick();
       return c;
      }


      ostream & operator<<(ostream& out,const Clock &c) {
       out << setfill('0') << setw(2) << c.hour << ':' << setw(2) << c.min;
       if(c.ap)
        out << " PM";
       else
        out << " AM";
       return out;
      }


      測試程序1和結(jié)果:



       


      測試程序2和結(jié)果:



       


       


      轉(zhuǎn)型構(gòu)造函數(shù)可以將其他類型轉(zhuǎn)換成所需的類的類型。如果要進(jìn)行相反的轉(zhuǎn)型動作,即要將類的類型轉(zhuǎn)換成其他類型,可以對轉(zhuǎn)型操作符進(jìn)行重載:


      operator othertype();  <====== 相對=====>轉(zhuǎn)型構(gòu)造函數(shù)


       注意: 聲明中不能包含返回類型,即使void也不行,但函數(shù)體中必須包含return語句,用來返回轉(zhuǎn)型結(jié)果


       


      雖然轉(zhuǎn)型操作符重載函數(shù)帶來很多便利,但仍需謹(jǐn)慎使用,因為編譯器嘗嘗在需要的時候調(diào)用轉(zhuǎn)型操作符重載函數(shù),而這些隱式的調(diào)用對程序員來說,是不可見的,特別是當(dāng)程序員并不希望發(fā)生這種調(diào)用時會產(chǎn)生無法預(yù)料的后果


       


      看例子:


      頭文件dict.h:          (注意該頭文件有一個問題,為什么friend不能對類的參數(shù)取值?。。”仨毎裦riend用的參數(shù)定義的外面?。。。?/span>


       


      #include <iostream>
      #include <string>
      using namespace std;


       



      /********************************************************************/
      class Entry;
      class Dict;
      ostream & operator<<(ostream &,const Entry &);
      ostream & operator<<(ostream &,const Dict &);
      /********************************************************************/


       


      class Entry {
      public:
         Entry() {flag = false;}
         void add(const string &,const string &);
         bool match(const string &) const;
         void operator=(const string &);
         void operator=(const char *);
         friend ostream & operator<<(ostream &,const Entry &);
         bool valid() const { return flag; }
         void del() { flag = false; }
      private:
         string word;
         string def;
         bool flag;
      };


       


      void Entry::operator=(const string &str) {
         def = str;
         flag = true;
      }


       


      void Entry::operator=(const char * str) {
         def = str;
         flag = true;
      }


       


      ostream & operator<<(ostream &out,const Entry &e) {
         out << e.word << "  defined as: " << e.def ;
         return out;
      }


       


      void Entry::add(const string &w,const string &d) {
         word = w;
         def = d;
      }


       


      bool Entry::match(const string &key) const {
         return key == word;
      }


       


      enum {MaxEntries = 100};


       


      class Dict {
      public: 
         friend ostream & operator<<(ostream &,const Dict &);
         void remove(const string &w);
         Entry & operator[] (const string &);
         Entry & operator[] (const char *);
      private:
         Entry entries[MaxEntries+1];


       


      };


       


      ostream & operator<<(ostream &out,const Dict &d) {
         for(int i = 0 ;i < MaxEntries; i++)
            if(d.entries[i].valid())
               out << d.entries[i] << endl;
         return out;
      }


       


      Entry &Dict::operator[](const string &k) {                  //返回引用是該程序的技巧。因為程序通過這個地方,和前面重載的=操作符填充字典返回因為是為了修改對應(yīng)的值,即賦值
         for(int i = 0;  i < MaxEntries && entries[i].valid(); i ++)
            if(entries[i].match(k))
               return entries[i];
         string not_found = "***not in dictionary";
         entries[i].add(k,not_found);
         return entries[i];
      }


       


      Entry & Dict::operator[](const char *k) {
         string s = k;
         return operator[](s);
      }


       


      void Dict::remove(const string &w)
      {
         int i,j;
         for(i = 0 ;i< MaxEntries; i ++)
            if(entries[i].valid() && entries[i].match(w))
               break;
         if(i == MaxEntries)
            return ;
         for(j = i + 1; j < MaxEntries && entries[j].valid() ; j++)
            entries[j-1] = entries[j];
         entries[j-1].del();                    //最后一個失靈,即最后一個標(biāo)志位設(shè)置為false,因為已經(jīng)移到前面了
      }


       


       


      測試程序和結(jié)果:


       



       


       


      內(nèi)存管理操作符new、new[]、delete和delete[]既可以用成員函數(shù)也可以用頂層函數(shù)重載


      嵌入式內(nèi)存有限,應(yīng)用程序經(jīng)常需要直接管理內(nèi)存


       


      new操作符重載:


      void * C::operator new(size_t size) {


        //...


      }



      void *  operator new(size_t  size) {


           //...


      }


      返回值void *


      new和new[]操作符重載函數(shù)的第一個參數(shù)必須是size_t類型,其數(shù)值等于被創(chuàng)建對象大小,其他參數(shù)是可選的


       


       


      delete操作符重載:


      void C::operator delete( void * objPtr) {


        //...


      }



      void operator delete(void *objPtr) {


         //...


      }


       


      delete和delete[]操作符重載函數(shù)的第一個參數(shù)必須是void*類型,返回值必須是void,而其他參數(shù)則是可選的


      看例子:


      頭文件frame.h:


      #include <iostream>
      #include <string>
      using namespace std;


      const int  MaxFrames = 4;
      const int  DataSize = 128;


      class Frame {
      public:
         Frame() { name = "NoName"; print(); }
         Frame(const char *n) { name = n; print(); }
         Frame(const string &n) { name = n ; print(); }
         Frame(const string&,const void *,unsigned);
         void print() const;
         void *operator new(size_t);


         void delete(void *);
      private:
         string name;
         unsigned char data[DataSize];
      };


      Frame * allFrames = 0;
      unsigned char framePool[MaxFrames * sizeof(Frame)];
      bool alloc[MaxFrames];


      Frame::Frame(const string &n,const void *d, unsigned bsize) {
         name = n;
         memcpy(data,d,bsize);
         print();
      }


      void Frame::print() const {
         cout << name << "  created.\n";
      }


      void * Frame::operator new(size_t size) {
         if(size != sizeof(Frame))
            throw string("Not a Frame");
         if(allFrames == 0) {
            allFrames = reinterpret_cast<Frame *>(framePool);
            for(int i = 0 ;i < MaxFrames ;i ++)
               alloc[i] = false;
          }
         for(int i = 0; i < MaxFrames ;i ++)
            if(!alloc[i]) {
               alloc[i] = true;
               return allFrames + i;
            }
         throw string("Out Of Storage");
         return 0;
      }


      void Frame::operator delete(void *adr) {


        int i = static_cast<unsigned char *>(adr) - framePool;


        i /= sizeof(Frame);


        alloc[i] = false;


      }


       


      測試程序和結(jié)果:


       



       


       


      一個類中的成員函數(shù)可以使另一個類的friend:




       


      常見編程錯誤:


      1,賦值操作符是唯一一個不能被繼承的操作符


      2,除了內(nèi)存管理操作符,所有的操作符要么以類成員函數(shù)形式重載,要么其參數(shù)列表中至少有一個類的對象


      3,[],(),=和->必須以成員函數(shù)重載


      4,如果一個一元操作符以頂層函數(shù)重載,必定有一個參數(shù)


        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多