6.27 用initializer_list 类型传参 求一列数的和
#include <iostream>
#include <string>
#include <initializer_list>
using namespace std;
int fun(std::initializer_list<int> list)
{
int sum = 0;
for (auto i = list.begin(); i != list.end(); i++)
{
sum += *i;
}
return sum;
}
int main()
{
int i = 1, j = 2, k = 3;
cout <<fun({i, j, k}) << endl; // 注意这里要加花括号
return 0;
}
//返回类型
#include <iostream>
using namespace std;
// 返回引用类型
const string & shoutstring(const string &str1, const string &str2)
{
return str1.size() <= str2.size() ? str1 : str2 ;
}// 都是用的const类型 所以其字符串值不变
// 返回string类型
6.32
知识点1:返回的引用无效:局部临时变量或者局部对象的引用对于返回都是无效的,因为在函数终止之后,局部变量或者对象的引用不再指向有效的内存区域。若是常量在函数调用之前存在,引用即可用。
知识点2:可以对返回值是非常量引用的函数结果赋值。
6.33写一个递归函数,输出vector对象的值
//注意传参
#include <iostream>
#include <vector>
using namespace std;
using iter = vector<int>::iterator;
void fun(iter beg, iter end) // 递归输出容器的值
{
if (beg != end)
cout << *beg++ << "\n";
else
return ;
fun(beg, end); // 递归
}
int main()
{
int a[5] = {1, 2, 3, 4, 5};
vector<int>b(a, a+5);
fun(b.begin(), b.end());
return 0;
}
6.36:编写一个函数声明,使其返回数组的引用并且该数组包含10个string对象(不要使用尾置返回类型,decltype或者类型别名)
int (*func(int val))[10];//括号要对,并且维数必须标明
/**************************************************
type (*function_name(parameter list))[dimension]
逐层的理解:func(int i),名为func的函数有一个int型的参数i
(*func(int i)),表明我们可以对函数返回的结果进行解引用操作
(*func(int i))[10],表明对函数的解引用可以得到大小为10的数组
int (*func(int i))[10],表示数组中的元素是int类型
**************************************************/
string (&func(string (&arrStr)[10]))[10]
6.37 为上一题在写三个声明:
using ArrT = string[10];
ArrT& func1(ArrT& arr);//使用类型别名
auto func2(ArrT& arr) -> string(&)[10]; //使用尾置返回类型
string arrS[10];
decltype(arrS)& func3(ArrT& arr);//使用decltype关键字
函数重载 重点
知识点:如果同一个作用域的几个函数的名字相同但形参不同,我们称之为重载函数
1:如果连个函数只有返回类型不同,则第二个声明错误
int fun(int i)
bool fun(int i) //错误
2:int fun(const string &);
int fun(string &) // 正确 指针也是正确的
但是如果是 (const int i) 和(int i) 错误
知识点:知识点1:函数反复调用的过程中重复出现的形参,这样的值被称为默认实参。该参数在使用过程中可以被用户指定,也可以使用默认数值
知识点2:调用含有默认实参的函数时,可以包含该实参,也可以省略该实参。
知识点3:一旦某个形参被赋予了默认值,其后所有形参都必须有默认值。
知识点4:顺序很重要!在设计函数时,将默认值的形参放在后面。
知识点5:在给定的作用域中,一个形参只能被赋予一次默认实参,且局部变量不能作为默认实参。
6.40:a正确 b错误 char background 缺少默认参数
6.41 a错误 应该为ht赋值, b正确, c 合法但是wd会被赋值成*
6.42
#include <iostream>
#include<string>
#include<vector>
using namespace std;
string make_plural(size_t ctr, const string& word, const string& ending = "s")//此处觉得题目描述有误,应该是第三个形参赋予"s",应为是字符串。
{
//size_t表示的是unsigned int
return (ctr > 1) ? word+ending : word;
}
int main(int argc, char *argv[])
{
cout<<"两单词的单数形式:"<<make_plural(1,"success","es")<<" "<<make_plural(1,"failure")<<endl;
cout<<"两单词的复数形式:"<<make_plural(2,"success","es")<<" "<<make_plural(2,"failure")<<endl;
return 0;//代表执行成功
}
6.47 目前还不太懂
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void digui(vector<int> &vec)
{
#ifndef NDEBUG
cout << "vector size:" << vec.size() << endl;
#endif
if (!vec.empty())
{
auto tmp = vec.back();
vec.pop_back();
digui(vec);
cout << tmp << " ";
}
}
int main()
{
vector<int> vec{1,2,3,4,5,6}; // 从方法在后面
digui(vec);
return 0;
}
函数匹配知识点:
选定调用函数的候选集,选出可行函数(
特征:1形参数量与本次调用提供的实参数量相等 2 每个实参的类型与对应的形参类型相同,或者能转换成形参的类型)
如果函数含有默认实参,则在调用时传入的实参可能少于它的实际使用实参数量
对于fun(1, 2.2)
声明为:fun(int,int)和fun(double double)报错
fun(long) 和fun(float) fun(3.14)二义性报错
因为就第一个实参来说选前一个好,就第二个实参来说选第二个好;这样会造成二义性所以错误
重载时最好避免强制类型转换
6.49:候选函数:选定本次调用对应的重载函数集,集合中的函数称为候选函数
6.51
#include <iostream>
using namespace std;
void f()
{
cout << i << " "<< j << endl;
}
void f(int i)
{
cout << i << endl;
}
void f(int i, int j)
{
cout << i << " " << j << endl;
}
void f(double i, double j)
{
cout << i << " " << j << endl;
}
int main()
{
f(2.56, 42); // 编译器报错
f(42);
f(42, 0);
f(2.56, 3.14);
return 0;
}
难点:————————
函数指针和指针函数
http://blog.sina.com.cn/s/blog_9e2e84050101cche.html
http://www.cnblogs.com/shenlian/archive/2011/05/21/2053149.html
http://wenku.baidu.com/view/e9efb70879563c1ec5da7153.html
指针函数:int * p (形参) 其返回值是一个int *类型 ,即返回指针的函数
函数指针 int (*p) (形参); int f(int); p = &f;
int (*f(int)) (int );
p 是指向返回值为 int的函数 的指针
上面就p而言 一个是函数名(指针函数), 一个是指针变量(函数指针)
6.54
知识点1:函数指针指向的是函数并非对象。想要声明一个指向函数的指针只要用指针替代函数名即可
知识点2:当我们把函数名当作一个值使用时,函数自动的转换为指针,直接赋予或者取址皆可。可以直接使用只想该函数的指针调用该函数。
知识点3:给指针赋予nullptr或者0时,指针不指向任何函数。
知识点4:函数重载时,指针的类型必须与重载函数精确匹配,包括形参类型数量和返回值类型。
知识点5:虽然不能返回一个函数,但是可以返回一个指向函数的指针。
bool (*p)(const string &, const string &)// p是一个指向一个函数返回值为bool 的指针,
int (*f(int))(int, int);//f有形参列表,f是个函数,f的返回值为指针,指针本身又有参数列表,因此指针指向的是函数,该函数的类型为int
//难点
#include <iostream>
#include<string>
#include<vector>
using namespace std;
int f(int a, int b)
{
return a+b;
}//声明定义该函数
int main(int argc, char** argv)
{
typedef int(*p)(int a, int b); //声明函数指针,未初始化,p为指向函数的指针。使用typedef的声明语句定义的不再是变量而是类型别名
//就是将变量转化为类型别名的一种方式,p原来是指向函数的指针变量,现在变成了指向函数的指针变量的类型别名
vector<p> a;
return 0;
}
//或者:
//这个更加全面
int func(int a, int b);
using pFunc1 = decltype(func) *;
typedef decltype(func) *pFunc2;
using pFunc3 = int (*)(int a, int b);
using pFunc4 = int(int a, int b);
typedef int(*pFunc5)(int a, int b);
using pFunc6 = decltype(func);
std::vector<pFunc1> vec1;
std::vector<pFunc2> vec2;
std::vector<pFunc3> vec3;
std::vector<pFunc4*> vec4;
std::vector<pFunc5> vec5;
std::vector<pFunc6*> vec6;
6.56
#include <iostream>
#include <vector>
#include <string>
using namespace std;
//typedef int(*p)(const int i, const int j);
int sum(const int i, const int j) // 加
{
return i+j;
}
int sub(const int i, const int j) // 减
{
return i - j;
}
int mul(const int i,const int j) // 乘
{
return i*j;
}
int di(const int i, const int j) // 除
{
return i/j;
}
//vector<p> a{sum, sub, mul, div};
int main()
{
typedef int(*p)(const int i, const int j);
// 声明函数指针,未初始化 p为指向函数指针。使用typedef声明语句定义的不再是变量而是类型名
//就是将变量转化类型别名的一种方法,p原来是指向函数的指针变量,现在变成了指向函数的指针变量的类型别名
vector<p> a{sum, sub, mul,di};
for (auto i = a.begin(); i != a.end(); i++)
{
cout << (*i)(4, 2) << " " << endl;
}
return 0;
}