|
|
|
《面向对象程序设计》自学方法指导 |
|
|
来源: 发布时间:2006-5-29 17:04:30 点击: |
函数定义的一般形式如下: 类型标识符 函数名(形式参数表) { 函数体; } 例如: int mul(int a,int b) { return a*b; } 这是一个函数定义。其中开头的int是函数类型,mul是函数名,int a和int b是形式参数表,花括号之内为函数体。这就申明了一个函数原型,在以后的程序中就可以调用了。要注意的一点是,调用过程中,各参数必须匹配,否则就会出错。 例如:#include<iostream.h> void putout(char *a,float b) { cout<< 〃a:〃<<a<<〃,〃<<〃b:〃<<b<<endl;} void main( ) { putout(12.3,12.3); //出错 } 我们注意到在调用函数的过程中,第一个参数是浮点数而不是字符型,所以在C++的编译过程中就会出错。函数原型增加了程序的可读性,从函数声明中就可以得知所有参数和返回值的类型。当我们把函数作为模块时,它也就相当于函数模块接口说明,为使用带来了方便。 (3)内联函数 C++中广泛使用函数,但是,函数的使用也造成了一定的额外开销,它占用内存,影响了程序运行速度。为此,C++提供了内联函数。内联函数与普通函数的不同之处在于,编译程序不把内联函数作为单独一段可调用代码,而是直接将它插入每个调用处。这样可以减少函数调用的额外开销;而且仍然允许程序以结构化方式进行组织。 内联函数与普通函数的定义并没有什么区别,只是在函数前面加一个关键字inline。就上面那个函数来说,只需在void前面加上inline即可。表面上看,确实没有什么区别,但在函数调用时,该函数并不是作为可调用函数使用,编译程序把它插入到每个调用putout()的地方。 C++编译程序把每个内联函数定义为宏,并把该宏插入到程序中每个调用该函数的地方。C++对内置函数进行预编译处理,并在程序的适当位置插入预先编译过的指令。从这个意义上说,用内联函数可以取代宏,这样可以更为灵活,而且没有什么副作用。 在使用内联函数时,应注意以下几点: ①内联函数必须在使用之前定义,因为内联函数的代码必须在插入到程序之前编译。 ②多数情况下,使用内联函数可能带来的主要问题是使程序增大;特别是对于代码量较大而又频繁调用的函数,程序量的增加会更多。因此,应注意限制内联函数的大小,不要仅仅为了提高几秒钟的速度而使程序变得庞大。一般情况下,内联函数应限制在5行以下。 ③联函数通常由赋值语句、表达式或简单的函数调用组成,不要含有if、for等控制结构。此外,递归函数不能作为内联函数。 3.关键字inline不是命令 如果程序中有关键字register,编译程序将忽略inline。 (1)引用:引用是C++的重点,函数之间,除了通过值传递参数之外,还可以通过引用传递参数。引用分为两种,即独立引用和引用参数。前者用于变量,后者用于函数。 简单的说,引用实际上是一种隐式指针,它为对象建立一个别名,引用通过操作符&来实现。&是地址操作符,可以用它获得地址,即指针。例如: int x; Int *xptr=&x; 定义了一个指针变量xptr,并把变量x的地址赋给该指针。把上面的定义稍作扩展,变为: int x; Int *xptr=&x; Int &xref=x; 该例定义了一个整型变量x和一个指向整型变量的指针,然后又设置xptr等于x的地址,因此&x和xptr的值是同一地址。接下来定义了一个引用,为整型变量xref,该变量同样被置成与x相同的地址。变量xptr和xref称为整型变量x的两个别名。与指针运算符*不同,引用操作符不是类型的一部分,即xptr的类型是整型指针,而xref只是整型,不能称之为引用整型。 独立引用对象只是其他对象的别名,对它的操作与对原来的操作具有相同的作用。例如: int I=0; int &ir=I; ir=2; 定义了一个引用变量ir,它是变量I的别名。假定初值相同,则对ir的操作与对I的操作完全一样。上例中的ir=2把2赋给I,&ir返回I的地址。执行ir=2与执行I=2等价。 指针变量与引用有两点主要区别:一是指针必须转换为与它所指向的变量相同的类型,以使赋值运算符两边的类型相匹配;而使用引用变量不需要类型转换。第二,指针变量和引用变量都用来指向其他变量,但指针变量使用的语法要复杂一些;而在定义了引用变量之后,其使用方法与普通变量相同。 引用对象在定义时必须初始化,已经定义,它的指针状况就无需再指明。 引用变量还常用于函数参数。例如自学参考中例1.6。当作为函数参数时,C++的引用类似于pascal和module--2中的var参数。当把较大的结构和对象传达给函数时,引用尤为重要。它不仅能节省时间和栈空间,而且在函数内部使用该结构也更方便。因此,将大的结构传送给函数时,最好通过引用来实现;有时候,即使不需要修改值,为了提高效率,也常常通过引用来传递参数。如果不想改变参数的值,可以用限定词const来避免。例如:Void yaba(const int & data),函数yaba接收通过引用传递过来的整数值(data).用const限定data的值不能修改。const限定词可以使我们更有效的使用引用,而不牺牲数据的完整性。 函数的返回值可以是引用,其-般形式为: 类型说明符 & 函数名(形参表) 可以看出,返回引用的函数的定义与普通函数的定义基本相同,但在函数名前有一个地址操作符&。调用返回引用的函数时。调用表达式可以出现在赋值号的左边。此外,在返回引用的函数的定义体时,return 语句的返回值通常是全局变量。具体例子如自学教材上page 12的例子。 对引用有以下限制: ①不能引用另一个引用(即不能得到引用的地址);不能建立引用数组,不能定义指向引用的指针;不能引用位段。 ②当定义引用变量时,除类成员、函数参数或返回值外,必须初始化。 (2)new和delete 至此,所提到的数据项的生存期仅有两种:静态的(static)和动态的(automatic)。由关键字static说明的数据项,在编译时分配到内存并在程序持续期间一直存在。这种数据项主要是全局变量(在程序体外说明的变量)。另一方面,automatic存储类的数据项,是特定程序体的局部。在程序运行中,遇到这种数据项的说明时,数据项从系统堆栈分配到内存,当数据项超出作用域时,释放内存--例如,程序已经执行过含有数据项说明的程序体时。然而,对于C++面向对象程序设计而言,仅有这两种是不够的。在C++的编程中,很难或者不可能预知内存的需求量,并且需要在运行期间,根据变化的情况(通常决定于用户通过程序界面表达的选择)随时地分配和释放内存。这种运行时分配和释放的内存被称为动态内存,对动态内存的处理称为动态内存管理。 C++中使用运算符new和delete来实现动态内存管理。这些运算符使程序员能够在程序运行期间的任一时刻为数据项分配内存,并且当数据项不再需要时回收内存。这种动态内存从一个称为堆(heap)的系统管理的数据结构那里分配得到。正如其名,new用于动态内存的分配,而delete用于动态内存的回收。在涉及类的地方,这些运算符和构造函数、析构函数结合起来作用。 运算符new用于任意类型的数据对象,不管它们是内建类型还是用户自定义的类。它适用于创建数据对象的类型,并为它所创建的对象返回一个指针(例如,那个对象在内存中的地址)。 例如: int * num_ptr; num_ptr=new int;//动态分配内存并将地址存于num_ptr。 或者 int *num_ptr=new int;可以得到同样的结果 我们也能用new为数组动态地分配内存空间,表达形式是上例所用表达形式的简单扩展。 |
|
|
|