?教学目的与要求:
了解对象的综合使用 。
掌握对象数组和对象指针的使用及对象作为函数参数 。
教学内容提要:
1,对象数组;
2,与对象有关指针;
3,对象作为函数参数教学重点:对象数组,对象指针 。
教学难点:对象数组,对象指针 。
教学进度,P74~P84
教学过程:
第 10 讲 对象数组和指针及对象作为函数参数数组名 [下标 ],成员名
1,声明:
2,访问方法:
类名 数组名 [元素个数 ];
3,对象数组的初始化:
数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。
通过初始化列表赋值。
例:
Point A[2]={Point(1,2),Point(3,4)};
如果没有为数组元素指定显式初始值,数组元素便使用缺省值初始化(调用缺省构造函数)。
【 10.1 对象数组 】
不声明构造函数,则采用缺省构造函数。
各元素对象的初值要求为相同的值时,可以声明具有缺省形参值的构造函数。
Point::Point(int x=0,int y=0)
{ X=x; Y=y;}
Point obj[4];
各元素对象的初值要求为不同的值时,需要声明带形参(无缺省值)的构造函数。
Point::Point(int x,int y)
{ X=x; Y=y;}
Point obj[3];//error
Piont obj[3]={Point(1,2),Point(3,4),Point(5,6)}
当数组中每一个对象被删除时,系统都要调用一次析构函数。
4.数组元素所属类的构造函数:
#include<iostream.h>
class Location
{ public:
Location( ) ;
Location(int xx,int yy);
~Location( ) ;
void Move(int x,int y);
int GetX( ) {return X;}
int GetY( ) {return Y;}
private:
int X,Y;
};
Location::Location( )
{ X=Y=0;
cout<<"Default Constructor
called."<<endl;
}
Location::Location(int xx,int yy)
{ X=xx;
Y=yy;
cout<< "Constructor
called."<<endl;
}
Locatuon::~Location( )
{
cout<<"Destructor called.“
<<endl;
}
void Location::Move(int x,int y)
{
X=x;
Y=y;
}
例 10.1
5.对象组应用举例:
Entering main...
Constructor called.
Constructor called.
Exiting main...
Destructor called.
Destructor called.
int main( )
{
cout<<"Entering main..."<<endl;
Location A[2]={Location(1,3),Location(4,5)};
for(int i=0;i<2;i++)
A[i].Move(i+10,i+20);
cout<<"Exiting main..."<<endl;
return 0;
}
通过对象的指针间接访问对象成员的方式相应地表示为:
因为间接访问运算符,*”的优先级低于成员选择运算符,.”,所以表达式中对象的指针名两边的 圆括号不能省略 。

1,对象的指针形式如下,类名 *对象的指针名声明一个指针来保存对象的地址,这个指针就是指向对象的指针,简称 对象的指针 。 对象的指针的声明方法与普通变量的指针相同。
( *对象的指针名),数据成员名 //访问数据成员
( *对象的指针名),成员函数名(参数表) //访问成员函数指针可以指向任一类型的变量,也可以 指向对象 。
【 10.2 与对象 有关的指针 】
例如 —-声明的类 Cylinder,可做如下声明和访问:
Cylinder cylinder1;
Cylinder *pcylinder=&cylinder1;
(*pcylinder).setcylinder(20.0,20.0);
(*pcylinder).surfacearea();
表述形式如下:
对象的指针名 ->数据成员名; //访问数据成员对象的指针名 ->成员函数名(参数表); //访问成员函数例如 —-声明的类 Cylinder,也可做如下声明和访问:
Cylinder cylinder1;
Cylinder *pcylinder=&cylinder1;
pcylinder ->setcylinder(20.0,20.0);
pcylinder->surfacearea();
,->”也叫做成员选择运算符,该运算符可用于通过对象的指针或结构变量的指针来访问其中的成员。
C++语言提供了另一个更常用的方法:
对象的指针的声明与访问
#include<iostream.h>
class Date //声明类
{
public:
Date(int y=2001,int m=1,int d=1); //带默认值的构造函数
~ Date(){} //析构函数
void setDate(int y,int m,int d); //用于改变日期的函数
void showDate() const; //用于输出日期的函数
private:
int year,month,day;
};
Date::Date(int y,int m,int d) //实现构造函数使用对象的指针前也一定要给指针赋一个合法的值。
例 10.2
{ year=y;
month=m;
day=d;
}
void Date::setDate(int y,int m,int d) //实现改变日期的函数
{ year=y;
month=m;
day=d;
}
void Date::showDate() const //实现输出日期的函数
{
cout<<year<<“年,<<month<<“月,<<day<<“日,<<endl;
}
void main()
{
Date date; //声明对象
Date *pdate=&date; //声明对象的指针
(续)
date.showDate(); //通过对象名访问公有成员函数
pdate->showDate(); //通过对象的指针访问公有成员函数
date.setDate(2001,6,30); //改变日期值
date.showDate();
pdate->showDate();
pdate->setDate(2001,12,31);
date.showDate();
pdate->showDate();
}
2001年 1月 1日
2001年 1月 1日
2001年 6月 30日
2001年 6月 30日
2001年 12月 31日
2001年 12月 31日
(续)
由于 this指针的隐含性,在一般情况下并不需要显式标明。
调用一个对象的成员函数时,编译系统会首先将这个对象的地址赋给被调用的成员函数中的 this指针,然后再调用成员函数。成员函数访问数据成员时就隐含地使用 this
指针来确保访问到的数据成员属于这个对象。

2,this指针比如,Date::Date(int y,int m,int d)
{
this->year=y;
this->month=m;
this->day=d;
}
说明:显式使用了 this指针,明确地表示出成员函数当前所操作的数据成员所属的对象。
this指针也是一个指向对象的指针,它隐含在类成员函数中,用来指向成员函数所属类的正在被操作的对象。
this指针的使用
#include<iostream.h>
class Date //声明类
{
public:
Date(int y=2001,int m=1,int d=1); //带缺省值的构造函数
~ Date(){} //析构函数
void setDate(int y,int m,int d); //用于改变日期的函数
void showDate() const; //用于输出日期的函数
private:
int year,month,day;
};
Date::Date(int y,int m,int d) //实现构造函数
{
this->year=y; //显式使用 this指针
this->month=m; //this指针指向正在被操作的对象例 10.3
this->day=d;
}
void Date::setDate(int y,int m,int d) //实现改变日期的函数
{ this->year=y; //显式使用 this指针
this->month=m; // this指针指向正在操作的对象
this->day=d;
}
void Date::showDate() const //实现输出日期的函数
{ cout<<this->year<<“年,<<this->month<<“月,
<<this->day<<“日,<<endl;
}
void main()
{
Date date(2001,1,1); //声明对象
Date *pdate=&date; //声明对象的指针
date.showDate(); //通过对象名访问公有成员函数
pdate->showDate(); //通过对象的指针访问公有成员函数
date.setDate(2001,6,30); //改变日期
(续)
3,指向类成员的指针
date.showDate();
pdate->showDate();
pdate->setDate(2001,12,31);
date.showDate();
pdate->showDate();
}
静态成员函数没有 this指针注类中的数据成员和成员函数在类实例化后在内存中也有一定的存储地址,可以声明指向类成员的指针 。通过这些指针,可以 访问对象的成员 。
指向类成员的指针指向成员函数的指针(简称成员函数指针)
指向数据成员的指针(简称数据成员指针)
说明:显式使用 this指针所完成的任务都可以由系统隐含完。
(续)
声明一个数据成员指针的形式如下:
数据类型 类名:,*数据成员指针名;
在这里赋值也就是确定指针指向类中的哪一个成员。
对于数据成员指针,赋值的形式如下:
数据成员指针名 =&类名::数据成员名对于下面声明的类 A比如,class A
{ public:
...
int a;
...
};
数据类型 是指数据成员指针所指向的数据成员的类型。
类名是数据成员所属类的名称。
在使用前必须声明并赋值
int A::*p=&A::a;
等价
int A::*p;
p=&A::a;
由于类本身是一个类型,不是变量,系统并不为类分配内存。在声明了指向类成员的指针后,还需要指定该类的一个对象来实例化这个类。
在使用时还必须通过指定的对象名或指向这个对象的指针来访问数据成员指针所指向的成员。
注访问数据成员的表述形式如下:
对象名,*类成员指针名 //通过对象名访问对象指针名 ->*类成员指针名 //通过对象的指针访问可以用下式声明指向这个类的数据成员 a的指针 p。
数据成员指针的使用
//EXAMPLE4_6.H
#include<iostream.h>
class A //声明类
{
public:
A(double x1=0.0,double y1=0.0);
~ A(){}
void setxy(double x1,double y1);
void outputxy() const;
double x;
private:
double y;
};
//EXAMPLE4_6.CPP
#include″EXAMPLE4_6.H″
A::A(double x1,double y1):x(x1),y(y1)
{
}
例 10.4
void A::setxy(double x1,double y1)
{
x=x1;
y=y1;
}
void A::outputxy() const
{
cout<<″x=\ t″<<x<<″\ ty=\ t″<<y<<endl;
}
void main()
{
A a(1.5,2.6),*pa=&a; //声明类 A的对象 a及指针 pa,并让对象 pa 指向 a
double A::*px=&A::x; //声明指向类 A的 double型数据成员的指针
//并使其指向公有成员 x
a.outputxy(); //调用成员函数输出
cout<<″a.x=\ t″<<a.x<<endl; //利用对象名直接访问成员 x
cout<<″a.*px=\ t″<<a.*px<<endl; //利用对象名和数据成员指针
//间 接访问 x
cout<<″pa->*px=\ t″<<pa->*px<<endl; //利用对象的指针和
//成员指针间接访问 x
}
(续)
x= 1.5 y=2.6
a.x= 1.5
a.*px= 1.5
pa->*px= 1.5
#include<iostream.h>
class Point
{ public:
Point( )
{ X=Y=0; cout<<"Default Constructor called.\n";}
Point(int xx,int yy);
{ X=xx; Y=yy; cout<< "Constructor called.\n"; }
~Point( ) { cout<<"Destructor called.\n"; }
int GetX( ) {return X;}
int GetY( ) {return Y;}
void Move(int x,int y) { X=x; Y=y; }
private:
int X,Y;
};
例 10.5
void main( )
{ cout<<"Step One:"<<endl;
Point *Ptr1=new Point;
delete Ptr1;
cout<<"Step Two:"<<endl;
Ptr1=new Point(1,2);
delete Ptr1;
}
运行结果:
Step One:
Default Constructor called.
Destructor called.
Step Two:
Constructor called.
Destructor called.
#include<iostream.h>
class Point
{ //类的声明同例,略
};
void main( )
{ Point *Ptr=new Point[2]; //创建对象数组
Ptr[0].Move(5,10); //通过指针访问数组元素的成员
Ptr[1].Move(15,20); //通过指针访问数组元素的成员
cout<<"Deleting..."<<endl;
delete[ ] Ptr; //删除整个对象数组
} 运行结果:
Default Constructor called.
Default Constructor called.
Deleting...
Destructor called.
Destructor called.
例 10.6
10.3.1 使用对象作为函数参数
【 10.3 向函数传递对象 】
例 10.7
#include<iostream.h>
class aClass
{
public:
aClass(int n) { i=n; }
void set(int n){ i=n; }
int get( ){ return i; }
private,int i;
};
void sqr(aClass ob)
{ ob.set(ob.get()*ob.get());
cout<<"copy of obj has i value of ";
cout<<ob.get()<<"\n";
}
void main()
{ aClass obj(10);
sqr(obj);
cout<<"But,obj.i is
unchanged in main:";
cout<<obj.get( );
}
10.3.2 使用对象指针作为函数参数例 10.8
#include<iostream.h>
class aClass
{ public:
aClass(int n) { i=n; }
void set(int n){ i=n; }
int get(){ return i;}
private,int i;
};
void sqr(aClass *ob)
{ ob->set(ob->get() * ob->get());
cout<<"Copy of obj has i value of ";
cout<<ob->get()<<"\n";
}
void main()
{ aClass obj(10);
sqr(&obj);
cout<<"Now,obj.i in
main() has been changed,";
cout<<obj.get() <<"\n";
}
10.3.3 使用对象引用作为函数参数
#include<iostream.h>
class aClass
{
public:
aClass(int n) { i=n; }
void set(int n){ i=n; }
int get(){ return i;}
private,int i;
};
void sqr(aClass& ob)
{ ob.set(ob.get() * ob.get());
cout<<"Copy of obj has i value of ";
cout<<ob.get()<<"\n";
}
void main()
{ aClass obj(10);
sqr(obj);
cout<<"Now,obj.i in main()
has been changed,";
cout<<obj.get() <<"\n";
}
作业:
2,对象指针使用
3、对象作为函数参数小结
P 110 3.24,3.25,3.26
1,对象数组的定义及初始化。