0%

C++之函数高级用法

C++之函数高级用法……

内联函数

  • 内联扩展是一种特别的用于消除调用函数时所造成的固有的时间消耗方法。
  • 一般用于能够快速执行的函数,因为在这种情况下函数调用的时间消耗显得更为突出。这种方法对于很小的函数也有空间上的益处,并且它也使得一些其他的优化成为可能
  • 使用方式:在原函数前加上inline关键字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
//内联函数,交换两个数的值
inline void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int m, n;
cout<<"Please enter two numbers:";
cin>>m>>n;
swap(&m, &n);
cout<<"The swap answer is:"<<m<<" "<<n<<endl;
return 0;
}

结果如下:

image-20221222184344724


引用变量

1.基本概念

  • C++给&符号赋予了另一个含义,将其用来声明引用,例如,要将rodents作为rats变量的别名,可以这样做:

    1
    2
    int rats;
    int &rodents = rats;
    • 就像声明中的char*指的是指向char的指针一样,int &指的是指向int的引用
    • 上述引用声明允许将rat和rodents互换,它们指向相同的值和内存单元
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include<iostream>
    using namespace std;

    int main(void)
    {
    int rats;
    int &rodents = rats;

    rats=100;

    cout<<"The rats is:"<<rats<<endl;
    cout<<"The rodents is:"<<rodents<<endl;

    cout<<"The &rats is:"<<&rats<<endl;
    cout<<"The &rodents is:"<<&rodents<<endl;

    int cats=50;
    rodents=cats;//仅仅代表赋值操作

    cout<<"The rats is:"<<rats<<endl;
    cout<<"The rodents is:"<<rodents<<endl;
    return 0;
    }

    结果如下:

    image-20221222190922339

  • 引用后变量就一直跟着最初引用指向的那个变量,如下例中rodents初始化为*pt使得rodents指向rats,接下来将pt改为指向bunnies,并不能改变这样的事实,即rodents引用的是rats

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include<iostream>
    using namespace std;

    int main(void)
    {
    int rats=101;
    int *pt=&rats;
    int &rodents=*pt;
    int bunnies=50;
    pt=&bunnies;

    cout<<"The rodents is:"<<rodents<<endl;
    return 0;
    }

    结果如下:

    image-20221222191816487

2.引用与结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<iostream>
#include<string>

using namespace std;

struct free_throws
{
string name;
int made;
int attempts;
float percent;
};

void set_pc(free_throws &ft);
void display(const free_throws &ft);
free_throws &accumulate(free_throws &target,const free_throws &source);

int main(void)
{
free_throws one={"Rick",13,14};
free_throws two={"Jack",10,16};
free_throws three={"Jerry",7,9};
free_throws four={"Jason",5,9};
free_throws five={"Micheal",6,14};
free_throws team={"class 1",0,0};

display(accumulate(accumulate(accumulate(accumulate(accumulate(team,one),two),three),four),five));

return 0;
}

void set_pc(free_throws &ft)
{
if(ft.attempts!=0)
ft.percent=100.0*float(ft.made)/float(ft.attempts);
}

void display(const free_throws &ft)
{
cout<<"Name:"<<ft.name<<endl;
cout<<"Made:"<<ft.made<<" \t";
cout<<"Attempts:"<<ft.attempts<<"\t";
cout<<"Percent:"<<ft.percent<<endl;
}

free_throws &accumulate(free_throws &target,const free_throws &source)
{
target.attempts+=source.attempts;
target.made+=source.made;
set_pc(target);
return target;
}

结果如下:

image-20221223223853436

3.引用与类对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
#include<string>

using namespace std;

string version1(const string &input,const string &add);
const string &version2(string &input,const string &add);

int main(void)
{
string input;
string result;

cout<<"Enter a string:";
getline(cin,input);

cout<<"Your string as entered:"<<input<<endl;
result=version1(input,"***");
cout<<"Your string enhanced is:"<<result<<endl;
cout<<"----------------------------------------"<<endl;

cout<<"Your string as entered:"<<input<<endl;
result=version2(input,"@@@");
cout<<"Your string enhanced is:"<<result<<endl;

return 0;
}

string version1(const string &input,const string &add)
{
string temp;
temp=add+input+add;
return temp;
}

const string &version2(string &input,const string &add)
{
input=add+input+add;
return input;
}

结果如下:

image-20221223231512315

4.引用与继承

  • ofstream对象可以使用ostream类的方法
  • ostream是基类,ofstream是派生类,派生类继承了基类的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<iostream>
#include<fstream>
#include<cstdlib>

using namespace std;

const int MAX=5;

void display(ostream &os,double arr[],int size);

int main(void)
{
const char *pt="scores.txt";
ofstream outFile;
outFile.open(pt);

if(!outFile.is_open())
{
cout<<"Could not open the file"<<endl;
cout<<"Program terminating"<<endl;
exit(EXIT_FAILURE);
}

double scores[MAX];
for(int i=0;i<MAX;i++)
{
cout<<"Please enter the score "<<i+1<<" is:";
cin>>scores[i];
}

display(cout,scores,MAX);
display(outFile,scores,MAX);

return 0;
}

void display(ostream &os,double arr[],int size)
{
for(int i=0;i<size;i++)
{
os<<"The score "<<i+1<<" is:"<<arr[i]<<endl;
}
}

结果如下:

image-20221224220257166

image-20221224220214614


函数重载

  • 可以通过函数重载来设计一系列函数:它们完成相同的工作,但使用不同的参数列表
  • 函数重载的判断方法是函数的参数列表不同,即参数的数目和类型不同,与函数的返回值无关
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<iostream>

using namespace std;

//显示字符串str的前n位
char *left(const char *str,int n);
//显示数字num的前ct位
unsigned long left(unsigned long num,unsigned int ct);

int main(void)
{
const char *trip="Hawaii";
unsigned long n=12345678;
char *temp;

for(int i=0;i<10;i++)
{
cout<<left(n,i)<<endl;
temp=left(trip,i);
cout<<temp<<endl;
cout<<"----------------------------"<<endl;
delete [] temp;
}
return 0;
}

char *left(const char *str,int n)
{
int m=0;

while(m<n && str[m]!='\0')
m++;//计算想要显示的字符串长度和真正的字符串长度哪个大,取最小的

char *p=new char[m+1];

int i;
for(i=0;i<m;i++)
p[i]=str[i];
p[i]='\0';

return p;
}

unsigned long left(unsigned long num,unsigned int ct)
{
unsigned long n=num;
unsigned int digits=1;

if(num==0||ct==0)
return -1;

while(n/=10)
digits++;//digits表示数字总共有几位

if(digits>ct)//ct表示想显示的位数
{
ct=digits-ct;
while(ct--)
num/=10;
return num;
}
else
return num;
}

结果如下:

image-20221225002135729


函数模板

  • 函数模板的定义格式:template<typename T>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include<iostream>

    using namespace std;

    template<typename T>
    void Swap(T &a,T &b);

    int main(void)
    {
    int a1,a2;
    double b1,b2;

    cout<<"Please enter two integers:";
    cin>>a1>>a2;
    Swap(a1,a2);
    cout<<"After Swap,the two integers:"<<a1<<" "<<a2<<endl;
    cout<<"--------------------------------------"<<endl;

    cout<<"Please enter two double datas:";
    cin>>b1>>b2;
    Swap(b1,b2);
    cout<<"After Swap,the two double datas:"<<b1<<" "<<b2<<endl;

    return 0;
    }

    template<typename T>
    void Swap(T &a,T &b)
    {
    T temp;
    temp=a;
    a=b;
    b=temp;
    }

    结果如下:

    image-20221225160532727

  • 显示具体化:template<> void Swap<student>(student &a,student &b)

  • 具体化优先于常规模板,而非模板函数优先于具体化和常规模板

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include<iostream>

    using namespace std;

    struct student
    {
    string name;
    double scores;
    };

    template<typename T>
    void Swap(T &a,T &b);

    template<> void Swap<student>(student &a,student &b);

    int main(void)
    {
    int a1=1,a2=2;
    double b1=9.77,b2=7.99;

    Swap(a1,a2);
    cout<<"After Swap,the two integers:"<<a1<<" "<<a2<<endl;
    cout<<"------------------------------------------"<<endl;

    Swap(b1,b2);
    cout<<"After Swap,the two double datas:"<<b1<<" "<<b2<<endl;
    cout<<"------------------------------------------"<<endl;

    student stu1={"ssy",99.87};
    student stu2={"wcf",68.94};
    cout<<"The original struct data:"<<endl;
    cout<<stu1.name<<" gets scores at:"<<stu1.scores<<endl;
    cout<<stu2.name<<" gets scores at:"<<stu2.scores<<endl;
    Swap(stu1,stu2);
    cout<<"After Swap,the result:"<<endl;
    cout<<stu1.name<<" gets scores at:"<<stu1.scores<<endl;
    cout<<stu2.name<<" gets scores at:"<<stu2.scores<<endl;
    return 0;
    }

    template<typename T>
    void Swap(T &a,T &b)
    {
    T temp;
    temp=a;
    a=b;
    b=temp;
    }//如果数据类型为student的执行了这个函数,那么结构体内的name和scores都会交换

    //显示具体化,即出现数据类型为student时,优先执行这个函数,而不是通用的Swap函数
    template<> void Swap<student>(student &a,student &b)
    {
    double temp;
    temp=a.scores;
    a.scores=b.scores;
    b.scores=temp;
    }

    结果如下:

    image-20221225164329097

  • 使用函数名<>强行使得编译器调用模板函数,<>中可以加数据类型,表示指定模板变量为对应数据类型变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include<iostream>

    using namespace std;

    template<typename T>
    T lesser(T a,T b);
    int lesser(int &a,int &b);

    int main(void)
    {
    int x=10,y=8;
    double a=9.87,b=7.56;
    cout<<"The lesser answer of x and y is:"<<endl;
    cout<<lesser(x,y)<<endl;
    cout<<"The lesser answer of a and b is:"<<endl;
    cout<<lesser(a,b)<<endl;
    cout<<"----------------------------------"<<endl;
    cout<<lesser<>(x,y)<<endl;//强制使用模板函数
    cout<<lesser<int>(a,b)<<endl;//使得传入的a,b强制转化为int类型
    cout<<lesser<int>(a,x)<<endl;
    return 0;
    }

    template<typename T>
    T lesser(T a,T b)
    {
    cout<<"Using template lesser!"<<endl;
    T result;
    result=a>b?b:a;
    return result;
    }

    int lesser(int &a,int &b)
    {
    cout<<"Using normal lesser!"<<endl;
    int result;
    result=a>b?b:a;
    return result;
    }

    结果如下:

    image-20221225191431660

欢迎来到ssy的世界