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 对象数组同一类的若干对象的集合组成对象数组。其定义形式与一般数组类似,例如:
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] 将对象作为函数参数实例EX4_10.CPP
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 对象数组同一类的若干对象的集合组成对象数组。其定义形式与一般数组类似,例如:
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] 将对象作为函数参数实例EX4_10.CPP