{C++]異常處理及函數

異常處理

需要人爲throw才能catch,與Java的機制有所區別

throw拋出的異常可以是任意類型

#include <stdexcept>
/*
 * ……
*/
int num[10] = {0};
try
{
    num[0] = num [1];
    throw num[0];
}
catch(int err)
{
    cout << "error happend" << endl;
}
try
{
    throw runtime_error("this is a run time error");
}
catch(runtime_error err)
{
    cout << err.what() << endl;
}


函數基礎

局部靜態變量

在程序的執行路徑第一次經過對象定義語句時初始化,直到程序終止時才銷燬。

int call_count()
{
    static int count = 0;
    return ++count;
}
int main()
{
    for(int i = 0; i < 5; i++)
    {
        call_count();
    }
    cout << call_count() << endl;    //the output is 6
}


使用引用參數傳遞省去拷貝


const參數

void fun(const int num); //num只能讀不能寫



可變形參的函數

類型相同,數量不同

void init_list_test(initializer_list<string> str)
{
    for(auto it = str.begin(); it != str.end; it++)
        cout << *it << " ";
    cout << endl;
}
init_list_test({"this", "is", "a", "test"});


省略符形參

#include <stdarg.h>
using namespace std;
void argFun(int parNum, ...)
{
    va_list ap;
    char* s;
    va_start(ap, parNum);
    for(int i = 0; i < parNum; i++)
    {
        s = va_arg(ap, char*);
        cout << s << endl;
    }
}
int main()
{
    argFun(3, "hello", "world", "!");
}

也可以只有省略號,完全忽略形參


尾置返回類型

用於返回類型比較複雜的情況,特別是沒有左值的類型

auto fun(int i) -> int (*)[10]        //等價於int (*fun(int i))[10]
{
    static int num[10];
    for(int j = 0; j < 10; j++)
    {
        num[j] = i + j;
    }
    return &num;
}
int main()
{
    void *result;
    result = fun(-5);
    int *temp;
    for(int i = 0; i < 10; i++)
        cout << *(temp = (((int*) result) + i)) << endl;


使用decltype,如下函數定義與上述方法等價

int type[10] = {0};
decltype(type) *fun(int i)


函數重載

同一作用域內的幾個函數名字相同但形參列表不同,返回值也可以不同

int func(int *ptr);
int func(int* const prt);        //重複聲明瞭前者
int func(const int *prt);        //新函數,作用域指向常量的指針
int func_new(int &num);
int func_new(const int &num);    //新函數,作用域常量引用

有無頂層const無法被區分,有無底層const可以被區

非常量可以轉化爲常量,所以比如當僅有3時,傳遞一個非常量的prt沒有錯誤,但若同時存在1,3,則編譯器會優先選擇1



const_cast強制轉換與重載

如下函數,即省去了函數返回值拷貝的過程,又解決了實參不是const類型時的麻煩

const int &func(const int &i, const int &j);
int &func(int &i, int &j);
int main()
{
    int m = 1, n = 3;
    int &result = m;
    result = func(m ,n);
    cout << result << endl;
}
const int &func(const int &i, const int &j)
{
    return (i > j) ? i : j;
}
int &func(int &i, int &j)
{
    const int &temp = func(const_cast<const int&>(i), const_cast<const int&>(j));
    return const_cast<int&>(temp);
}

const_cast還可用於多線程下volatile關鍵字


避免二義性調用

當有多個函數可以匹配時


默認實參

int caculateSquare(int width = 10, int length = 10);

調用時只能省去尾部的實參


內聯函數

直接替換,省去開銷,一般較小,不支持遞歸

inline int getMax(int i, int j);

內聯函數必須是和函數體申明在一起,纔有效。

內聯函數和宏很類似,而區別在於,宏是由預處理器對宏進行替代,不檢查函數參數,返回值,而內聯函數是通過編譯器控制來實現的。而且內聯函數是真正的函數,只是在需要用到的時候,內聯函數像宏一樣的展開,所以取消了函數的參數壓棧,減少了調用的開銷。你可以象調用函數一樣來調用內聯函數,而不必擔心會產生於處理宏的一些問題。


constexpr

用於常量表達式的函數

返回值及所有形參類型比學位字面值類型,函數體中必須只有一條return語句

可以返回非常量,編譯器檢查上下文

通常放在頭文件中


調試幫助:assert與NDEBUG

assert是一種預處理宏,包含在頭文件assert.h中

assert(expr);    expr爲假時,打印錯誤,退出;expr爲真時,doing nothing

assert的缺點是極大影響程序的性能,產生額外開銷

調試結束後可以在#include<assert.h>前加入#define NDEBUG來使所有assert失效

可以利用NDEBUG編寫自己的調試代碼

#ifndef NDEBUG
    cerr << "error:NDEBUG test success"   ;
#endif

預處理器還提供了幾個對於調試很有用的局部靜態變量

__func__    當前調試的函數名

__FILE__    存放當前文件名

__LINE__    當前行號

__TIME__    文件編譯時間

__DATE__    文件編譯日期


函數指針

聲明一個函數指針

bool (*prtf)(double x, int n);    //未初始化

可以直接給prtf賦值

int sum(int x, int y)
{
    return x + y;
}
prtf1 = sum;
prtf2 = &sum;//等價
prtf1(1,2);
(*prtf)(1,2);    //等價

重載函數也可以有函數指針

函數指針可以作爲形參傳入  

int prtfPara(int x, int y, int (*prtf) (int m, int n))
{
    return prtf(x, y) + x;
}
cout << prtfPara(1, 2, sum) <<endl;

可以用typedef和decltype定義函數的類型,避免冗長和繁瑣

typedef int functype1(int x, int y);
typedef decltype(sum) *functype2;
int prtfPara(int x, int y, functype2 prtf)


返回函數指針的函數

typedef int(*PF)(int x, int y) ;
PF pf1(int x)
{
    return sum;
}
functype1 *func1 = pf1(1);
cout << func1(4, 5) << endl;

也可這樣聲明func1

int (*func2(int m))(int x, int y);


注意:當decltype作用於某個函數時,它返回函數類型而不是指針類型,需要顯式加上*表明是指針類型,例如functype2




最近開的書比較多,上週末又病了一場,節奏有點不太對,有待調整!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章