C++步步为营

C++---CHAPTER 6: FUNCTION

2019-07-13  本文已影响0人  世界上的一道风

参数传递

  1. 传值调用
void reset(int *p)
{
  *ip = 0; // 改变指针ip所指对象的值
   ip = 0; // 只改变了ip的局部拷贝,实参未被改变
{

2.传引用调用

void fn(const int i) {/* fn能读取i,但是不能向i写入值*/}
string is_sentence(const string &s)
{
  string::size_type ctr = 0;
  return find_char(s, '.',ctr) == s.size() - 1 && ctr == 1;
}

其中如果find_char的第一个形参是普通引用string&,程序会失败,因为s是常量引用。

返回类型和return语句

char &get_val(string &*str, string::size_type ix)
{
  return str[ix];
}
int main()
{
  string s("a value");
  cout << s << endl;
  get_val(s, 0) = 'A'; // 将s[0]的值改为A
cout<< s << endl;
}

如果返回类型是常量引用,则不能给结果赋值:

shorterString("hi", "bye") = "X"; //错误,返回类型是一个常量
vector<string> process()
{
  if (expected.empty())
  return {}; // 返回一个空的vector对象
else if (expected == actual)
  return {"functionX", "okey");  //返回列表初始化的vector
else
  return {"functionX", expected, actual};
}
int arr[10];
int (*p2)[10] = &arr; //p2是一个指针,指向含有10个整数的数组

int (* func(int i))[10];  //解引用func的调用得到一个大小为10的数组
auto func(int i)->int(*)[10];  //func返回的类型是一个指针,该指针指向含有10个整数的数组。
int odd[] = {1,2,3,4,5};
int even[] = {3,4,52,,5,1};
// 已知返回一个指针指向5个整数的数组
decltype(odd) *arrPtr(int i)
{
  return (i % 2) ? &odd : &even; //返回一个指向数组的指针
}

注:decltype表示他的返回类型是个指针,并且该指针所指的对象与odd的类型一致。但是decltype不会把数组类型转换成对应的指针,所以decltype的结果是一个数组,要表示arrPtr是一个指针,必须在函数声明的时候加上一个*

Record  lookup(Phone);
Record lookup(const Phone); //重复声明了上面的函数

当形参是某种类型的指针或引用,则区分常量对象和非常量对象可以实现函数重载:

Record lookup(Account&);  //作用于Account的引用
Record lookup(const Account&); // 新函数,作用于常量引用
#include <iostream>
#include <string>
using namespace std;

const string &shorterString(const string &s1, const string &s2)
{
    return s1.size() <= s2.size() ? s1 : s2;
}
string &shorterString(string &s1, string &s2)
{
  auto &r = shorterString(const_cast<const string&>(s1),const_cast<const string&>(s2));
  return const_cast<string&>(r);
}
int main() {

  string s1{"pig"};
  string s2{"dunk"};
  string &ans1 = shorterString(s1,s1);
  cout <<" ans1 is " << ans1 << endl;
  const string s3{"moster"};
  const string s4{"tigger"};
  const string &ans2 = shorterString(s3,s4);
  cout <<" ans2 is " << ans2 << endl;
}

constexpr  int new_sz() {return 42;}
constexpr int foo = new_sz(); //正确 foo是一个常量表达式

constexpr size_t scale(size_t cnt){
    return new_sz() * cnt;
 }
int arr[scale(2)]; // 正确:scale(2)是常量表达式
int i = 2; //i不是常量表达式
int a2[scale(i)]; //错误

注: 对于某个给定的内联函数或者constexpr函数来说,它的多个定义必须完全一致。因此,内联函数和constexpr函数通常定义在头文件中。

__FILE__   
__LINE__
__TIME__
__DATE__
__FUNC__
bool lengthCompare(const string&, const string &);
bool (*pf) (const string &, const string &); // 未初始化,pf指向一个函数,该函数的参数是两个const string的引用,返回值是bool类型
pf = lengthCompare;  // pf 指向名为lengthcompare的函数
pf = &lengthCompare;  //  等价上式


bool b1 = pf("hello", "goodbye"); // 调用lengthcompare函数
bool b2 = (*pf)("hello", "goodbye"); //等价的调用
// 第三个形参是函数类型,自动转换为指向函数的指针;
void useBigger(const string &s1, const string &s2, bool pf(const string &, const tring &));
//等价的声明
void useBigger(const string &s1, const string &s2, bool (*pf) (const string &, const tring &));

这就能直接把函数作为实参使用:

useBigger(s1, s2, lengthCompare);
// Func与Func2是函数类型
typedef bool Func(const string &, const string &);
typedef bool decltype(lengthCompare) Func2; //等价的类型

// 下面两个是指向函数的指针
typedef bool(*FuncP) (const string&, const string&);
typedef decltype(lengthCompare) *FuncP2; // 等价的类型

注:

  1. 含有typedef的声明语句定义的不在是变量而是类型别名。
  2. decltype返回函数类型,不会将函数类型自动转换为指针类型,所以结果的前面加上*,得到指针。

使用的时候:

void useBigger(const string &s1, const string &s2, Func);
void useBigger(const string &s1, const string &s2, FuncP2);

使用类型别名:

using F = int(int* , int); // F是函数类型不是指针
using PF = int(*)(int *, int); // PF是之真理类型
PF f1(int);  // PF是指向函数的指针,f1返回指向函数的指针

尾置返回类型的方式声明一个返回函数指针的函数:

auto f1(int) -> int(*) (int*, int);
上一篇下一篇

猜你喜欢

热点阅读