1、在函數重載中,主要通過參數類型的不同來重載,而不能通過傳回值不同來重載。在函數的參數預設值的設定中要注意不要和函數重載弄混,比如:
void output( int x);
void output( int x, float y=0.0);
這樣就有二義行,如果有函數調用output(a)(a在這裡為一整形數)時,不知道該調用哪個,產生錯誤!
2、在函數傳回值為地址或引用時應該注意傳回值不能是局部變數,應該是全域變數、靜態變數等,靜態變數(只在定義的局部函數裡面可見)和全域變數共用全域資料區,在整個函數運行期間都存在,雖然用局部變數暫時可以得到正確的答案,如:
#include <iostream.h>
int *f(int x,int y)
{
int *z;
int temp=x+y;
z=&temp;
return z;
}
int f1()
{
cout<<"what wrong?"<<endl;
return 0;
}
int main()
{
int a,b;
int *c;
cin>>a>>b;
c=f(a,b);
cout<<*c<<endl;
f1();
cout<<*c;
return 0;
}
這個函數如果輸入2,3則輸出是:
5
what wrong?
-858993460
調用函數f1後再輸出的c所指向的值是一個不確定的值,因為這個時候函數f已經結束,它用來返回的臨時變數也在程式做了一些別的事情後被覆蓋掉或釋放。
3、參數傳遞傳遞指標和引用主要是為了效率,當一個資料類型很大時,因為傳值要複製副本,所以不可取,但是另一方面由於指標和引用傳遞時參數容易被修改,所以我們在參數傳遞的時候加上關鍵字const用來限制調用函數對參數的改變。比如函式宣告可以這樣寫:int fn(const int & a);則在這個函數裡面,雖然a和實際參數指向的是同一地址單元,但是因為是const的,所以其值不可改變。
4、const int *ip;指向常量的指標,其指標值可以變,但是它所指記憶體中的值不可以改變(記憶體中的內容為常量);
int *const ip=&i;指標常量,其指標值不可以改變,但是它所指向記憶體中的值可以改變,並且在定義的時候需要賦初值;
const int *const ip=&i;指向常量的常量指標,定義時也需要初始化。
5、如果運算子被重載為全域函數,那麼只有一個參數的運算子叫做一元運算子,有兩個參數的運算子叫做二元運算子。如果運算子被重載為類的成員函數,那麼一元運算子沒有參數,二元運算子只有一個右側參數,因為對象自己成了左側參數。其中運算子的重載規則如下:
運算子 規則
所有的一元運算子 建議重載為成員函數
= () [] -> 只能重載為成員函數
+= -= /= *= &= |= ~= %= >>= <<= 建議重載為成員函數
所有其它運算子 建議重載為全域函數
6、this指標指向調用函數的那個對象。此條很容易解釋第5條為什麼運算子多載為類的成員函數時一元運算子沒有參數,二元運算子只有一個右側參數。
關於第2點的體會:
#include <iostream.h>
int *f(int x,int y)
{
int *z;
int temp=x+y;
z=&temp;
return z;
}
int f1()
{
cout<<"what wrong?"<<endl;
return 0;
}
int main()
{
int a,b;
int *c;
cin>>a>>b;
c=f(a,b);
cout<<*c<<endl;
f1();
cout<<*c;
return 0;
}
這個函數如果輸入2,3則輸出是:
5
what wrong?
-858993460
調用函數f1後再輸出的c所指向的值是一個不確定的值,因為這個時候函數f()已經結束,它用來返回的臨時變數也在程式做了一些別的事情後被覆蓋掉或釋放。
讓我們來看這個很有趣的程式:
#include <iostream.h>
int *z;
int *f(int x,int y)
{
int temp=x+y;
z=&temp;
return z;
}
int f1()
{
cout<<"what wrong?"<<endl;
return 0;
}
int main()
{
int a,b;
int *c;
cin>>a>>b;
c=f(a,b);
cout<<*c<<endl;
f1();
cout<<*c;
return 0;
}
這裡把z定義為全域的整形指標變數,然後把局部變數中x+y的值所指的地址給z返回,z為全域變數應該不存在上面臨時變數被釋放的情況,但實際上啟動並執行到的結果出乎意料,還是:
5
what wrong?
-858993460
問題出在哪裡?開始的時候我百思不得其解,甚至問老師老師也不太清楚,後來在網友的協助下(看樣子在網上學習很有用的)得到了答案,原來在函數f()中,temp是局部變數,在函數返回後它棧裡面的值都要被釋放,而指標z是指向局部變數temp的,所以得到上面的結果,於是將f()改成:
int *f(int x,int y)
{
*z=x+y;
return z;
}
再運行原以為可以得到正確的結果,但啟動並執行時候出錯了,再想想,原來定義全域指標變數z的時候並沒有給它賦初值,這個時候指標的指向是不定的,所以運行時會出錯,於是將定義改成int *z=new int;只是此時z成了堆中的資料,不再是放在全域資料區裡面的了。
要想讓全域資料區裡面的資料返回被調函數的地址,可以把上面的全域變數聲明改成int z;,函數f(x,y)中改成z=temp;return &z;就可以了。