第八天
20:28
1.函数的形参
可变形参的函数
传入多个同一类型的值 如果函数的实参数量未知但是全部实参的类型都相同。我们可以使用intializer_list 类型的形参。intializer_list 是一种标准库类型。用于表示某种特定类型的值的数组.大部分操作和一般的vector、数组的差不多。
initializer_list<T> lst;
inttializer_list<T> lst{a,b,c};
lst2(lst)
lst2 = lst
lst.size()
lst.begin()
lst.end
声明列表中所含元素的类型
intitializer_list<string> ls;
intitializer_list<int> li;
和vector不一样的是该方法得到的对象中的元素永远是常量值,我们无法改变该声明中的对象元素的值,类似于元组tuple
举个例子
void error_msg(intitializer_list<string> il){
for (auto beg = il.begin(); beg != il.end(); ++beg)
cout << *beg << " ";
}
if (expected != actual)
error_msg({"functionx", expected, actual})
else
error_msg({"functionx", "okay"})
上述这个就是比较期望值和真实值差不多,该函数的功能就是打印出来,但是只需要一个形参就可以了,可以输出同一个类型多个常量,都是const类型,不能是变量 下面换一个例子
void error_msg(Err_Code e, initializer_list<string> il){
cout << e.msg() <<": ";
for (const auto &elem : il)
cout << elem << " ";
cout << endl;
}
这里输出的时候const auto和auto应该都可以 要注意的是上面initializer_list<string> 定义是在后面的,这就要求我们在调用函数的时候前面第一个值要给Err_Code 所定义的变量。
省略符形参
简单的提一下
void foo(parm_list, ...)
void foo(...)
第一种形式指定了foo 函数的部分形参的类型,后面的形参无需进行类型检查,在第一种形式后面的逗号是可选的
2.返回类型和return
第一种是无返回值的函数,第二种是有返回值的函数。 无返回值的函数就是void 定义,不再多说。
有返回值函数
假如说是bool、string、int 或者其他类型定义的函数是不能没有返回值的,例如return; 无返回值就会报错
string make_plural(size_t ctr, const string &word, cosnt string &ending){
return (ctr > 1) ? word + ending : word;
}
const string &shroterString(const string &s1, const string &s2){
return s1.size() <= s2.size() ? s1 : s2;
}
上面的函数是返回的类型是string ,意味着返回值将被拷贝到调用点。 下面的函数的形参和返回类型都是const string 的引用,不管是调用函数还是返回类型都不会真正拷贝string 对象。
注意:不要返回局部对象的引用或指针
cosnt string &manip(){
string ret;
if (!ret.empty)
return ret;
else
return "Empty";
}
不能返回ret ,因为ret 是一个局部变量,不能返回“empty” ,因为他是一个局部临时量。
c++11新标准的规定,可以返回花括号包围的值的列表。如下
vector<string> process(){
if (expected.empty())
return {};
else if (expected == actual)
return {"functionX", "okay"};
else
return {"functionX", expected, actual};
}
第一条return 语句返回的是一个空列表,此时,process 函数返回的vector 对象是空的。如果expected 不为空,根据expected 和actual 是否相等,函数返回的vector 对象分别用两个或三个元素初始化。 如果说函数返回的是内置类型,就是函数内部定义的,则花括号里只能包含一个值。
主函数main 的返回值,如果说编译器到达了main 函数的结尾处没有返回值,那么编译器将会隐式地插入一条返回0的return 语句。 main 函数的返回值可以看作是状态指示器。返回0表示执行成功,返回其他值表示执行失败,其中非0值的具体含义依机器而定。
递归
int factorial(int val){
if (val >1)
return factorial(val - 1) * val;
}
声明一个返回数组指针的函数
要想在声明func 时不适用类型别名,我们必须记住定义的名字后面的数组维度 格式如下所示
Type (*function (parameter_list)) [dimension]
int (*func(int i)) [10];
auto func(int i) -> int (*) [10];
我们使用一般的从内向外的方法来理解一下 func(int i) 表示调用func 函数时需要一个int类型的实参。 (*func(int i)) 意味着我们得到的函数调用的结果执行解引用操作。 (*func(int i)) [10] 表示解引用func 的调用将得到一个大小是10的数组。 int (*func(int i)) [10] 表示得到的维度是10的数组的元素是int 类型。
下面是使用decltype返回
int odd[] = {1, 3, 5, 7, 9};
int even[] = {0, 2, 4, 6, 8};
decltype(odd) *arrPtr(int i){
return (1%2) ? odd : &even;
}
3. 函数重载
函数重载可以理解为,同一个函数,也就是同名函数,他们要对不同的数据类型进行处理,为了方便记忆,我们就把他们定义为同名函数,对不同类型的变量进行相同的处理。举例
void print(const char *cp);
void print(const int *beg, const int *end);
void print(const int ia[], size_t size);
int j[2] = {0, 1};
print("hello world");
print(j, end(j) - begin(j));
print(begin(j), end(j));
注意:main函数不能重载
下面是关于查找的例子
Record lookup(const Account&);
Record lookup(const Phone&);
Record lookup(const Name&);
上述是调用三个类型的引用来查找记录,编译器会自动根据数据的类型来选择函数。 重载函数可能在相残数量或者形参类型上有所不同,但是在上述代码中只有参数类型不同。 假设有两个函数,他们呢的形参列表相同但是返回类型不同,则第二个函数类型是错误的
Record lookup(const Account&)
bool lookup(const Account&)
有时候两个相残列表看起来不一样,但是实际上是相同的
Record lookup(const Account &acct)
Record lookup(const Account&)
typedef Phone Telno;
Record lookup(const Phone&)
Record lookup(const Telno&)
4. 函数指针
函数指针指向的函数而非对象。和其他指针一样,函数指针指向某种特定类型,函数的类型由他的返回类型和形参类型共同决定,与函数名无关。
bool lengthCompare (const string&, const string &);
bool (*pf)(const string &, const string &);
pf是一个指向函数的指针,其中函数的参数是两个const string引用,返回的是bool类型。 第一种方法,将函数名作为一个值使用的时候,该指针自动指向函数。
pf = lengthCompare;
pf = &lengthCompare;
调用函数与等价调用
bool b1 = pf("hello", "goodbye");
bool b3 = (*pf)("hello", "goodbye");
bool b1 = lengthCompare("hello", "goodbye");
string::size_type sumLength(const string&, const string&)
bool cstringCompare(const char*, const char*)
pf = 0;
pf = sumLength;
pf = cstringCompare;
pf = lengthCompare;
够详细了,必须要函数的返回类型和形参类型精确匹配,才能够使用函数指针
重载函数的指针
void ff(int*);
void ff(unsigned int);
void (*pf1)(unsigned int) = ff;
void (*pf2)(int) = ff;
double (*pf3)(int*) = ff;
返回函数的指针
没看太懂,不是很敢写,上面只是说明了定义,没有将使用,回头再补把
今日结束 22:21,今天没什么好说的把,自从开始写博客了,感觉每天都好忙,没时间做其他的,其他的时间就是学学专业课,记记单词,一个星期没打游戏了,确实也没觉得太上瘾,还好,主要是真的太充实了 对了,今天也看了一点分析数据结构的基础,二分查找还有一些递归,明天就从头开始写数据结构了,虽然说cppp还有很多包括类都没看,时间有点太长了,数据结构尽量对算法写的详细一点把,上面代码还是很多的,到时候再手打出来估计可能就不大行了,到时候再想办法把
|