C++学习随笔5 基于过程编程(1)- 函数

基于函数的程序设计就称为基于过程的程序设计

1.函数机制

  • 栈机制:

一个程序要运行,就要先将可执行程序文件装载到计算机的内存中。装载是操作系统掌控的,一般而言,操作系统将程序装入到内存后,将形成一个随时可以运行的进程空间。

一个运行的程序在内存中表示为四个空间区域:

代码区:存放程序的执行代码。所谓执行代码就是索引了的一个一个函数块代码,它由函数定义块的编译得到。

全局数据区:存放全局数据、常量、文字量、静态全局量和静态局部量。

堆区:存放动态内存,供程序随机申请使用。

栈区:存放函数数据区(即局部数据区),它动态地反应了程序运行中的函数状态,其运动轨迹正好用来观察函数的调用与返回。

调用一个函数,可以看作是一个栈中元素的压栈和退栈操作。然而,压栈之后的函数运行,可能导致其他函数被调用。因此,程序运行表现为栈中一系列元素的压栈和退栈。

最初,操作系统将main函数压入栈中,标志着程序运行的开始,等到最后main函数退栈,程序也就运行结束了。

  • 函数指针:

数据指针(Pointer to Data):指向数据区域的指针。

函数指针(Function Pointer):指向代码区域的指针(也称为指向函数的指针(Pointer to Function))。

指针函数(Pointer Function):返回指针类型的函数。  例如:int* f(int a);

运行中的程序,其中的每个函数都存放在代码区,占据着一个区域。故每个函数都有起始地址,函数指针与数据指针不能相互转换,通过函数指针可以调用所指向的函数。

 

函数指针定义:

函数有多少种类型,函数指针就有多少种类型。函数的类型表示是函数声明去掉函数名。 例如: void f();  类型就是 void ();


函数指针定义:
int (*gp) (int); //定义一个名为gp的函数指针,容纳函数指针名的括号不能省
函数指针初始化:
int g(int);
int (*gp)(int) = g;    //其中g应该与指针gp所指向的函数类型相同

函数指针赋值:
int g(int);
int (*gp)(int);
gp = g;
函数指针声明:
typedef int (*Fun)(int a, int b);    //是函数指针的声明不是定义
因此:
int m(int, int);
Fun func = m;   //OK
Fun = m;          //错:不恰当地使用typedef 'Fun'
函数引用:
void g();
typedef void Fun();
Fun &f=g;
f();         //等价于g()

函数指针既可以作为参数传递,也可以作为数组的元素类型。

  • 命令行与main参数

命令行重定向:

如果不专门指定设备,就是标准输入/输出,否则,“<”后面规定输入设备,“>”后面规定输出设备。

例如:

#include <iostream>
using namespace std;

int main(){
    for(int a,b; cin>>a>>b; cout<<a+b<<"\n");  
}

通过命令"ConsoleApplication1<abc.txt>>xyz.txt",便可以从abc.txt文件中读入数据,而将输出追加到文件xyz.txt中(>则是不追加,每次清空)。

命令"ConsoleApplication1"则是默认使用标准输入/输出。

main参数:

int main(int argc, char**argv){......}

 第一项是表示传递的C-串有几个,第二项是表示具体的C-串数组

#include <iostream>
using namespace std;

int main(int argc, char **argv)
{
  for(int i=0; i<argc; ++i)
      cout<<argv[i]<<endl;  
}

  • 函数重载

只要参数个数不同,参数类型不同,参数顺序不同,函数就可以重载。然而,返回类型不同则不允许函数重载。

默认参数:

C++可以给函数声明中的参数使用默认参数。这样在函数调用时,对应的实参就可以省略。函数参数的默认值只能从后往前设置

void func(int a=1, int b, int c=3, int d=4);   //错,a和b的位置违规
void func(int a, int b=2, int c=3, int d=4);  //ok

调用时,默认实参也只能从后往前逐个替换:
func(10, 15, 20, 30);           //ok
func();                         //错:a没有默认值,必须给出实参
func(12, 12);                   //ok: c和d默认
func(2, 15, , 20);              //错:d不默认则c也无资格默认

 

posted @ 2016-11-27 17:52  etcjd  阅读(214)  评论(0)    收藏  举报