在函式宣告中可以設定若干個預設引數,這些引數在函式呼叫時可以省略。例如:
void
print
(inta=
3,intb=4
)print
();// 3 4
print(4
);// 4 4
print(,3
);// compile error
預設引數提供了更靈活的函式宣告。簡化函式邏輯的同時,也提供了一種擴充套件既有函式的方式。
在很多情況下,函式的宣告與定義是分開的。語法上講我們可以在宣告時給出缺省引數, 也可以在定義時給出缺省引數。然而在函式呼叫處,編譯器會進行語法檢查, 被呼叫的「函式簽名」是否存在、是否有歧義,只取決於呼叫處可見的那個函式(宣告或定義)。
我們知道可以通過引數個數的不同來進行函式過載。唯一需要注意的是過載函式呼叫的二義性。 通過引數個數進行過載的函式被呼叫時,便有可能存在歧義。例如:
void
print
(inta=
1){}
void
print
(inta=
1,intb=2
){}print
();
同時定義上述兩個print
函式沒有問題,因為它們的函式簽名是不同的。但print()
的呼叫存在歧義,此處會發生編譯錯誤。 因此,使用預設引數時,要避免函式過載的二義性。
除了虛函式外,函式呼叫的函式位址是在編譯期決定的。可變引數是指乙個函式可以接受可變數目的引數,在c語言中最常見的便是
printf
和scanf
。 它們是如何實現的呢?
當然這不是函式過載,我們只定義乙個函式,它可以接受任意個引數。我們知道函式呼叫前需要將引數壓棧,預設情況下c++會將引數從右向左順序壓棧。 棧空間是從高位址向低位址生長的,故第乙個引數擁有最低的位址。 獲取第乙個引數後,我們只要知道後續引數的型別和個數,就可以逐個按照位址取出來。
在dll生成和跨語言的過程呼叫時,常常遇到壓棧順序和由誰清空引數棧的問題,它們可以在函式宣告中加入類似如何定義乙個可變引數的函式?c++提供了stdarg.h標頭檔案,它定義了若干巨集來方便上述的操作。 首先使用_stdcall
、_cdecl
等關鍵字來指定。
va_list
來獲取引數棧,va_start
來指定第乙個引數的位址。 此後便可以使用va_arg()
來獲取後續的引數了,這時需要指定型別(因為需要確定空間大小)。 最後用va_end
來釋放資源。乙個簡單的可變引數的函式像這樣:
#include
void
my_print
(int
count
,...)
第乙個引數是必不可少的,我們需要用它來確定引數的個數。
python函式大全手稿
floor round ceil max min sum abs divmod 獲取商和餘數 pow index count upper lowwer swapcase capitalize eval exec help isinstance issubclass globals reversed ...
C 手稿 運算子過載
運算子過載就是對已有的c 運算子賦予更多的語義,讓乙個運算子可以作用於其他的資料型別。典型地,讓運算子接受乙個類的物件作為引數。通常有兩種方式來過載乙個運算子 宣告乙個普通函式,作為類的友元。宣告為類的成員方法。事實上,運算子的本質是函式。每個運算子呼叫會轉換為函式呼叫,運算子的運算元轉換為函式引數...
c 函式指標與預設引數
include using namespace std inline void printa void printb int int a 4 void printc int a,int b,int c 3,int d 4 預設引數寫右邊 typedef void mytypefunc int a,i...