4.5类与对象的进一步用法 本节将进一步讨论类与对象使用的一些基本工具,而有关高级设计使用技巧,在后续章 节中再作分析和讲解。 4.5.1类对象指针 利用指向对象的指针来访问对象成员,与通过指针访问结构变量的形式相同。但是,对 于一个复杂的类对象,特别是类的成员存在不同访问权限、继承限制、消息机制等问题,如 何认识对象指针与普通指针的差异,正确地使用指针的长处,是要认真探讨的问题。 下面是一个对象指针的例子: class myclass! int maino myclass ob(120)定义 myclass类的对象ob p=&ob;使p指向ob ∥可以使用p-> member name操作 注意:语句 myclass*tp:是创建一个指向 myclass类对象的指针,而不是创建一个对象 (1)、指向类数据成员的指针与普通指针不同: ①必须考虑数据成员的存取权限,即受限于数据封装保护。 ②必须考虑到其所属的类范围 (2)、指向类成员函数的指针必须具备的条件: ①与成员函数的返回类型相同 ②与成员函数的参数表完全相同。 ③与成员函数所属类相同 (3)、指向静态成员的指针的用法: 由于静态成员只有一个存储副本,因此在定义指向静态成员的指针时,与一般指针相同。 但仍必须有类范围,且其函数的返回值类型和参数表必须相同。 Class stap private public static void set(int n)i.i void(*sp)(int)=&sap:set;∥指向成员函数的指针 ntmp=&stap:val/指向私有成员的指针 注意存取限制,上面的语句在友元函数中是可以用的 使用静态成员指针,不通过该类对象,与一般指针变量使用方法一样,如: sp(4)
4.5 类与对象的进一步用法 本节将进一步讨论类与对象使用的一些基本工具,而有关高级设计使用技巧,在后续章 节中再作分析和讲解。 4.5.1 类对象指针 利用指向对象的指针来访问对象成员,与通过指针访问结构变量的形式相同。但是,对 于一个复杂的类对象,特别是类的成员存在不同访问权限、继承限制、消息机制等问题,如 何认识对象指针与普通指针的差异,正确地使用指针的长处,是要认真探讨的问题。 下面是一个对象指针的例子: class myclass{. . .}; int main() { myclass ob(120);//定义 myclass 类的对象 ob myclass *p; p=&ob;//使 p 指向 ob . //可以使用 p->member_name 操作 . } 注意:语句 myclass *p;是创建一个指向 myclass 类对象的指针,而不是创建一个对象。 (1)、指向类数据成员的指针与普通指针不同: ①必须考虑数据成员的存取权限,即受限于数据封装保护。 ②必须考虑到其所属的类范围。 (2)、指向类成员函数的指针必须具备的条件: ①与成员函数的返回类型相同。 ②与成员函数的参数表完全相同。 ③与成员函数所属类相同。 (3)、指向静态成员的指针的用法: 由于静态成员只有一个存储副本,因此在定义指向静态成员的指针时,与一般指针相同。 但仍必须有类范围,且其函数的返回值类型和参数表必须相同。 Class stap { private: static int val; public: static void set(int n){. . .} . . }; void (*sp)(int)=&stap::set;//指向成员函数的指针。 int *mp=&stap::val;//指向私有成员的指针。 注意存取限制,上面的语句在友元函数中是可以用的。 使用静态成员指针,不通过该类对象,与一般指针变量使用方法一样,如: *mp=4;sp(4);
4.5.2对象数组 同一类的若干对象的集合组成对象数组。其定义形式与一般数组类似,例如 complex ob array[10J∥定义一个 complex类的10个对象组成的数组 E complex*ob array=new complex[ 10] 访问其成员可以使用如下形式 ob array] class member; /数组元素.成员名 应注意避免的问题 (1)、对类对象数组中的元素初始化,必须通过该类的构造函数来进行。 (2)、若在定义带有类的对象数组时,不想立即对数组中对象赋初值,其构造函数中必 须含有一个不带参数的或是缺省参数的构造函数。 (3)、如果程序中以new分配数组存储空间,则将来释放此类数组所占用的存储空间 使用语句 delete ob array;是有问题的。应当使用如下形式: delete [ ob array;系统自动计算数组的容量。 这样指明共有多少对象元素释放,编译器才会逐个调用构构函数来释放。 4.5.3友元函数 友元函数( friend function)不是类的成员函数,但它可以访问类的私有元素。这是设计 者希望不通过类的成员函数去访问类的私有成员时使用的方式。即友元函数是在类的封装上 开了一个特殊通道 友元函数的定义是在常规函数的原型说明上加上关键字 friend 个类的友元函数,在该类说明中必须包括友元函数的原型说明。但要注意,友元函数 并不是类的成员函数,而是被允许访问该类所有对象的私有成员、独立于类的外界介入函数 [例4.9]友元函数使用实例EX49CPP。 注意:(1)、友元函数没有this指针,因此在访问哪个对象的私有成员时需要显式地确 定对象。 (2)、友元函数可以是多个类的友元。如果要进行两个类的定量比较时,经常使 用一个友元函数。 (3)、除了一般函数可以作为友元外,一个类的成员函数也可以是另一个类的友 元,只是在声明友元函数时要加上成员函数所在的类名。这样两个类可以合作完成某些任务, 便于协调处理。 (4)、当一个类中所有成员函数都有可以访问另一个类中私有成员时,称为友元 类。在类的说明中,对声明的语句是: friend class class name [例4.9a]两个类协同工作的实例EX49aCPP(?) 4.5.4对象作函数参数 把类对象作为变量传递给函数的方法,与传递其他数据类型变量的方法一样。有三种方 (1)、传值调用方式。说明函数的参数是属于某个类,调用函数时,就以该类对象作为 变量传递给函数,即复制了对象备份。在调用结束,释放对象备份时,调用了析构函数。 (2)、传址或引用方式。使用这两种方式,在函数返回时不会调用析构函数。 (3)、利用复制构造函数
4.5.2 对象数组 同一类的若干对象的集合组成对象数组。其定义形式与一般数组类似,例如: class complex{. . .}; complex ob_array[10];//定义一个 complex 类的 10 个对象组成的数组 或 complex *ob_array=new complex[10]; 访问其成员可以使用如下形式: ob_array[i].class_member;//数组元素.成员名 应注意避免的问题: (1)、对类对象数组中的元素初始化,必须通过该类的构造函数来进行。 (2)、若在定义带有类的对象数组时,不想立即对数组中对象赋初值,其构造函数中必 须含有一个不带参数的或是缺省参数的构造函数。 (3)、如果程序中以 new 分配数组存储空间,则将来释放此类数组所占用的存储空间 使用语句 delete ob_array;是有问题的。应当使用如下形式: delete []ob_array;//系统自动计算数组的容量。 这样指明共有多少对象元素释放,编译器才会逐个调用构构函数来释放。 4.5.3 友元函数 友元函数(friend function)不是类的成员函数,但它可以访问类的私有元素。这是设计 者希望不通过类的成员函数去访问类的私有成员时使用的方式。即友元函数是在类的封装上 开了一个特殊通道。 友元函数的定义是在常规函数的原型说明上加上关键字 friend。 一个类的友元函数,在该类说明中必须包括友元函数的原型说明。但要注意,友元函数 并不是类的成员函数,而是被允许访问该类所有对象的私有成员、独立于类的外界介入函数。 [例 4.9] 友元函数使用实例 EX4_9.CPP。 注意:(1)、友元函数没有 this 指针,因此在访问哪个对象的私有成员时需要显式地确 定对象。 (2)、友元函数可以是多个类的友元。如果要进行两个类的定量比较时,经常使 用一个友元函数。 (3)、除了一般函数可以作为友元外, 一个类的成员函数也可以是另一个类的友 元,只是在声明友元函数时要加上成员函数所在的类名。这样两个类可以合作完成某些任务, 便于协调处理。 (4)、当一个类中所有成员函数都有可以访问另一个类中私有成员时,称为友元 类。在类的说明中,对声明的语句是:friend class class_name; [例 4.9a] 两个类协同工作的实例 EX4_9a.CPP(?)。 4.5.4 对象作函数参数 把类对象作为变量传递给函数的方法,与传递其他数据类型变量的方法一样。有三种方 法: (1)、传值调用方式。说明函数的参数是属于某个类,调用函数时,就以该类对象作为 变量传递给函数,即复制了对象备份。在调用结束,释放对象备份时,调用了析构函数。 (2)、传址或引用方式。使用这两种方式,在函数返回时不会调用析构函数。 (3)、利用复制构造函数
例4.10将对象作为函数参数实例EX410.CPP
[例 4.10] 将对象作为函数参数实例 EX4_10.CPP