{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




最近开的书比较多,上周末又病了一场,节奏有点不太对,有待调整!

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