程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> java 賦值運算符、拷貝初始化和this指針

java 賦值運算符、拷貝初始化和this指針

編輯:更多關於編程

       1)首先區別什麼是賦值,什麼是初始化。

      2)程序中重載采用了引用傳遞,原因:①眾所周知,用值傳遞的參數將在要傳遞的函數內產生一個副本,沒有例外。如果這個對象很大,則副本就會浪費汗多空間。②在某些情況下可能想記錄對象的數目。如果編譯器在使用賦值運算符時,每次產生一個額外的對象,這樣就可能見到比醫療多得多的對象。而引用傳遞有助於避免創建過多的對象。

      3)return alpha(data); 返回值是重載函數所在的對象的一個副本,而不是同一個對象。返回的值可使它將運算符=串聯起來:a3=a2=a1;

      4) 然而alpha operator = (alpha& a)中值的返回與值的參數一樣的缺點:浪費內存空間。但是使用引用來返回函數的值如alpha& operator = (alpha& a) 這樣行嗎?

      回答是不行的:在函數內部創建的非static的局部變量,在函數返回時即被銷毀,引用所返回的值,僅僅是實際希望返回值得地址,是沒有意義的,甚至會出現嚴重錯誤。(在這裡我們可以用this指針解決這個問題,後文會解釋)

      注意:賦值運算符是唯一一個不能繼承的運算符。如果在基類重載了賦值運算符,那麼在任何派生類中都不能再重載同一函數。

     代碼如下  

    #include<iostream>
    using namespace std;
    class  alpha
    {
    public:
     alpha():data(0) {}       //沒有參數的構造函數
     alpha(int d):data(d) {}  //一個參數的構造函數
     void diplay()            //顯示數據
     {
      cout<<data<<endl;
     }
     alpha(alpha& a)          //重載拷貝構造函數
     {
      data=a.data;
      cout<<"copy constructor invoked! "<<endl;
     }
     alpha operator = (alpha& a) //重載賦值運算符
     {
      data=a.data;
      cout<<"assignment operator invoked! "<<endl;
      return alpha(data);  //單參數的構造函數
     }
    private:
     int data;
    };
    int main()
    {
     alpha a1(32);

     alpha a2;     //無參數構造函數
     a2=a1;        //賦值運算符
     a2.diplay();

     alpha a3=a1;  //拷貝構造函數
     a3.diplay();

     alpha a4(a1);  //拷貝構造函數
     a4.diplay();

     return 0;
    }

      .看函數的幾種情況

      1)函數參數

      view sourceprint?void func(alpha); //以值傳遞對象

      func(a1); //函數調用

      這時拷貝構造函數將會被調用來創建一個對象a1的副本,並將副本交給函數func()操作。(當然引用或者指針就不會調用拷貝構造函數)

      2)函數返回值

      view sourceprint?alpha func() //函數聲明

      a2=func() //函數調用

      在這裡:首先,程序調用拷貝構造函數來穿件一個func()返回值的副本;

      然後,這個值再被賦給a2(調用賦值運算符)。

      3)拷貝構造函數為alpha(alpha& a) ,為什麼不是alpha(alpha a)的形式?

      答:拷貝構造函數必須使用引用,否則會報告內存溢出。(因為如果參數用值來傳遞,就需要創建一個該值的副本。如何創建副本呢?使用拷貝構造函數,但是原函數本來就是要定義拷貝構造函數,這樣不斷調用自己你說會有什麼結果!~)

      二、this指針

      每一個對象的成員函數都可以訪問一種神奇的指針,即指向該對象本身的this指針,因而在任何對象中都可找到所屬對象的自身地址。

     代碼如下  

    #include<iostream>
    using namespace std;
    class  alpha
    {
    public:
     alpha():data(0) {}       
     alpha(int d):data(d) {}  
     void display()            
     {
      cout<<data<<endl
       <<this->data<<endl;
     }
     //alpha operator = (alpha& a) //重載賦值運算符
     //{
     // data=a.data;
     // cout<<"assignment operator invoked! "<<endl;
     // return alpha(data);  //單參數的構造函數
     //}
     alpha& operator = (alpha& a) //重載賦值運算符
     {
      data=a.data;
      cout<<"assignment operator invoked! "<<endl;
      return *this;     //通過this指針返回值
     }
    private:
     int data;
    };
    int main()
    {
     alpha a1(37);
     a1.display();  //直接輸出和this->data的輸出結果是一樣的
     alpha a2,a3;
     a3=a2=a1;    //調用賦值運算符
     cout<<"a2=";a2.display();
     cout<<"a3=";a3.display();
     return 0;
    }

      注意實例中的:使用this指針返回值。(從成員函數和重載運算符返回值,this指針是一個更實用的用法)

      1)this指針指向的是該成員函數所屬的對象,所以*this就是這個對象本身。通常實用引用和this指針從重載賦值運算符返回數據,從而避免創建額外的對象。

      2)必須注意:this指針在靜態成員函數中是無效的,因為靜態成員函數不屬於任何特定的對象。

      三、dynamic_cast和typeid

      這兩個功能通常使用在有很多類都由一個基類派生的情況下。為了使動態類型轉換能夠工作,基類必須是多態的(也就是說至少包含一個虛函數)。

      1.dynamic_cast可以改變指針類型

     代碼如下  

    #include<iostream>
    #include<typeinfo>
    using namespace std;
    class Base
    {
    public:
     Base() {}
     virtual void vertfunc()  //要想用dynamic_cast,基類必須是多態類型
     {}
     Base(int b):ba(b){}
     void show()
     {
      cout<<"Base: ba="<<ba<<endl;
     }
    protected:
     int ba;
    };
    class derv1:public Base
    {};
    class derv2:public Base
    {
    public:
     derv2():Base() {}
     derv2(int b,int d):Base(b),da(d) {}
     void show()
     {
      cout<<"derv2: ba="<<ba<<" da="<<da<<endl;
     }
    private:
     int da;
    };
    bool isDerv1(Base* pUnknown)
    {
     derv1* pderv1;
     if (pderv1=dynamic_cast<derv1*>(pUnknown))
      return true;
     else
      return false;
    }
    int main()
    {
     derv1* d1=new derv1;
     derv2* d2=new derv2;
     if (isDerv1(d1))
      cout<<"d1是類derv1的一個對象"<<endl;
     else
      cout<<"d1不是類derv1的一個對象"<<endl;
     if (isDerv1(d2))
      cout<<"d2是類derv1的一個對象"<<endl;
     else
      cout<<"d2不是類derv1的一個對象"<<endl;

     Base* pbase=new Base(10);
     derv2* pderv=new derv2(22,33);
     pbase->show();pbase=dynamic_cast<Base*>(pderv); pbase->show(); //派生類到基類
     pbase=new derv2(34,32);
     pderv->show(); pderv=dynamic_cast<derv2*>(pbase); pderv->show();  //基類到派生類
     return 0;
    }

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved