1)首先區(qū)別什么是賦值,什么是初始化。
2)程序中重載采用了引用傳遞,原因:①眾所周知,用值傳遞的參數(shù)將在要傳遞的函數(shù)內(nèi)產(chǎn)生一個副本,沒有例外。如果這個對象很大,則副本就會浪費汗多空間。②在某些情況下可能想記錄對象的數(shù)目。如果編譯器在使用賦值運算符時,每次產(chǎn)生一個額外的對象,這樣就可能見到比醫(yī)療多得多的對象。而引用傳遞有助于避免創(chuàng)建過多的對象。
3)return alpha(data); 返回值是重載函數(shù)所在的對象的一個副本,而不是同一個對象。返回的值可使它將運算符=串聯(lián)起來:a3=a2=a1;
4) 然而alpha operator = (alpha& a)中值的返回與值的參數(shù)一樣的缺點:浪費內(nèi)存空間。但是使用引用來返回函數(shù)的值如alpha& operator = (alpha& a) 這樣行嗎?
回答是不行的:在函數(shù)內(nèi)部創(chuàng)建的非static的局部變量,在函數(shù)返回時即被銷毀,引用所返回的值,僅僅是實際希望返回值得地址,是沒有意義的,甚至?xí)霈F(xiàn)嚴(yán)重錯誤。(在這里我們可以用this指針解決這個問題,后文會解釋)
注意:賦值運算符是唯一一個不能繼承的運算符。如果在基類重載了賦值運算符,那么在任何派生類中都不能再重載同一函數(shù)。
代碼如下:
#include<iostream>
using namespace std;
class alpha
{
public:
alpha():data(0) {} //沒有參數(shù)的構(gòu)造函數(shù)
alpha(int d):data(d) {} //一個參數(shù)的構(gòu)造函數(shù)
void diplay() //顯示數(shù)據(jù)
{
cout<<data<<endl;
}
alpha(alpha& a) //重載拷貝構(gòu)造函數(shù)
{
data=a.data;
cout<<"copy constructor invoked! "<<endl;
}
alpha operator = (alpha& a) //重載賦值運算符
{
data=a.data;
cout<<"assignment operator invoked! "<<endl;
return alpha(data); //單參數(shù)的構(gòu)造函數(shù)
}
private:
int data;
};
int main()
{
alpha a1(32);
alpha a2; //無參數(shù)構(gòu)造函數(shù)
a2=a1; //賦值運算符
a2.diplay();
alpha a3=a1; //拷貝構(gòu)造函數(shù)
a3.diplay();
alpha a4(a1); //拷貝構(gòu)造函數(shù)
a4.diplay();
return 0;
}
.看函數(shù)的幾種情況
1)函數(shù)參數(shù)
view sourceprint?void func(alpha); //以值傳遞對象
func(a1); //函數(shù)調(diào)用
這時拷貝構(gòu)造函數(shù)將會被調(diào)用來創(chuàng)建一個對象a1的副本,并將副本交給函數(shù)func()操作。(當(dāng)然引用或者指針就不會調(diào)用拷貝構(gòu)造函數(shù))
2)函數(shù)返回值
view sourceprint?alpha func() //函數(shù)聲明
a2=func() //函數(shù)調(diào)用
在這里:首先,程序調(diào)用拷貝構(gòu)造函數(shù)來穿件一個func()返回值的副本;
然后,這個值再被賦給a2(調(diào)用賦值運算符)。
3)拷貝構(gòu)造函數(shù)為alpha(alpha& a) ,為什么不是alpha(alpha a)的形式?
答:拷貝構(gòu)造函數(shù)必須使用引用,否則會報告內(nèi)存溢出。(因為如果參數(shù)用值來傳遞,就需要創(chuàng)建一個該值的副本。如何創(chuàng)建副本呢?使用拷貝構(gòu)造函數(shù),但是原函數(shù)本來就是要定義拷貝構(gòu)造函數(shù),這樣不斷調(diào)用自己你說會有什么結(jié)果!~)
二、this指針
每一個對象的成員函數(shù)都可以訪問一種神奇的指針,即指向該對象本身的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); //單參數(shù)的構(gòu)造函數(shù)
//}
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的輸出結(jié)果是一樣的
alpha a2,a3;
a3=a2=a1; //調(diào)用賦值運算符
cout<<"a2=";a2.display();
cout<<"a3=";a3.display();
return 0;
}
注意實例中的:使用this指針返回值。(從成員函數(shù)和重載運算符返回值,this指針是一個更實用的用法)
1)this指針指向的是該成員函數(shù)所屬的對象,所以*this就是這個對象本身。通常實用引用和this指針從重載賦值運算符返回數(shù)據(jù),從而避免創(chuàng)建額外的對象。
2)必須注意:this指針在靜態(tài)成員函數(shù)中是無效的,因為靜態(tài)成員函數(shù)不屬于任何特定的對象。
三、dynamic_cast和typeid
這兩個功能通常使用在有很多類都由一個基類派生的情況下。為了使動態(tài)類型轉(zhuǎn)換能夠工作,基類必須是多態(tài)的(也就是說至少包含一個虛函數(shù))。
1.dynamic_cast可以改變指針類型
代碼如下:
#include<iostream>
#include<typeinfo>
using namespace std;
class Base
{
public:
Base() {}
virtual void vertfunc() //要想用dynamic_cast,基類必須是多態(tài)類型
{}
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;
}
更多信息請查看IT技術(shù)專欄