第二章 面向对象的编程风格(如何编写函数)

来源:互联网 发布:方舟生存进化优化mod 编辑:程序博客网 时间:2024/06/06 02:51

2.1  如何编写函数

 

fibonacci函数:1 1 2 3 5 8 13 21......

程序:编写一个函数

该函数返回fibonacci数列中由用户指定的某个位置的元素。例如用户可以询问fibonacci数列的第八个元素是什么?

我们的程序回答是21.

 

int fibon_elem(int pos);                 

int elem=1;
int n_2=1,n_1=1;
for(int ix=3;ix<pos;++ix)
{
   elem=n_1+n_2;
   n_2=n_1;
   n_1=elem;
}
 return elem;
//如果用户取得是第一或第二个元素,则FOR循环不会执行。因为elem的原值就为1.如果用户取第三及以后的元素则会运行循环部分,直到ix超过pos。位于pos处的元素值会被存储到elem变量中。

 

程序改进:

如果用户输入一个不合理的数值,如0或者负数。fibon_elem()会返回1,而这是一个错误的答案。所以程序:

法一:

#include <cstdlib>
if(pos<=0)
exit(-1);

exit()函数:终止整个程序,但我们必须传给函数一个值,此值将成为程序结束时候的状态值。以状态值-1结束程序。

法二:

抛出异常(exception),在第七章会详细谈到。


法三:

改变返回值,使其得以表示fibon_elem()是否能计算出用户想要的值。

bool fibon_elem(int pos,int &elem)       //bool函数用来检测位置值是否合理
{
  if(pos<=0||pos>1024)                            //int为有符号参数,有上限,为防止溢出,随便设定一个足够大的数字1024大小。

elem=0;

return false;

}
elem=1;
//位置值为1和2时候,elem的值为1.
int n_2=1,n_1=1;
for(int ix=3;ix<=pos;++ix)
{
elem=n_1+n_2;
n_2=n_1;
n_1=elem;
}
return true;
}

上述例子中,有两个参数。而函数只能返回一个函数值。pos参数作用是:fibon_elem()能否计算出所指定的元素,关系到返回值为true或false.剩下的问题是,如何返回该函数的实际值。做法之一就是加入第二个参数:&elem。这使我们从这个函数中返回两个值。

#include<iostread>
using namespace std;
bool fibon_elem(int,int&);//函数声明中没有写出两个参数的名称,没有问题。因为参数名称只有在函数内使用参数才是必要的。
                                              //fibon_elem()前置声明,目的是让编译器知道它的存在

int main()
{
   int pos;
cout<<"please enter a position:";
cin>>pos;
int elem;
if(fibon_elem(pos,elem))
cout<<"element # "<<pos
    <<"is"<<"elem"<<end1;
else cout<<"sorry,could not calculate element #"
<<pos<<end1;

}

编译完成后的结果:
please enter a position:12
element # 12 is 144

 

总程序:

 

#include<iostream>
using namespace std;
bool fibon_elem(int,int&);
int main()
{
int elem_pos;
cout<<"plese enter an polision of the Fibonacci";
cin>>elem_pos;
int elem;
if(fibon_elem(elem_pos,elem))
cout<<"element #"
    <<elem_pos
    <<"is"
    <<elem
    <<endl;
else cout<<"sorry,couldn't calculate the element #"<<elem_pos<<endl;

}
bool fibon_elem(int pos,int&elem)
{
if(pos<=0||pos>2014)
{
elem=0;
return false;
}
elem=1;
int n_2=1,n_1=1;
for(int ix=3;ix<=pos;++ix)
{
elem=n_2+n_1;
n_1=n_2;
n_2=elem;
}
return true;

}

 


程序改进:


如果函数的返回类型不为void,那么它必须在每个可能的退出点上把值返回。
函数中的每一条return语句都被用来明确表示该处就是函数的退出点。
如果函数的最后一条不是return,那么最后一条语句之后就是该函数的隐式退出点。

下面程序就是因隐式退出点并未返回任何数值,而无法编译。
bool printf_sequence(int pos)
{
 if(pos<=10||pose>1024)
{
 cerr<<"invalid position:"
<<pos
<<"--cannot handle request!\n";
return false;//隐式退出点并未返回任何数值
cout<<"the fibonacci sequence for:"
<<pos
<<"position:\n\t";

 

 

//所有的位置都会打出1   1,只有pos==1除外                   
switch(pos)

  default:
  case2:
  cout<<"1";
//注意此处没有break
  case 1:
  cout<<"1";
  break;
 
}

int elem;
int n_2=1,n_1=1;
for(int ix=3;ix<=pos;++ix)
{
 elem=n_2+n_1;
n_2=n_1;
n_1=elem;
//一行打印十个元素
cout<<elem<<(!(ix%10)?"\n\t":"");

}

cout<<end1;
//此处会产生编译错误
//此处为隐式退出点....没有return语句

}

print_sequence有两个退出点,但我们只指定了一条return语句。隐式退出点位于最后一条语句之后。我们的实现代码中,只有位置不合理时才将数值返回!而幸运的是,编译器捕捉到了这个问题,并将其标注错误。我们必须加上return true作为最后的一条语句。
现在我们在原本的main()函数,在调用过fibon_elem之后对print_sequence()的调用。编译执行后,程序输出一下结果:
please enter a position:12
element # 12 is 144
the fibonacci sequence for 12 positions:
1 1 2 3 5 8 13 34 55
89 144


return语句的第二种形式不返回任何数值。这种形式只在返回值为void时才会被使用,它用来提前结束函数的执行

void print_mag(ostream &os,const string &msg)
{
  if(msg.empty())
//不打印任何信息,结束函数
  return;
  os<<msg;
}
本例不需要再最后面加上return语句,由于不需要返回任何值u,所以隐式退出点已经足够。

0 0