版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
内容提要:1第7章类和对象7.1面向对象的程序设计7.2类与对象7.3构造函数与析构函数7.4this指针7.5静态成员7.6常对象与常成员7.7习题7.1面向对象的程序设计2编程案例:现有5个三角形,需要编程计算这些三角形的周长和面积。面向过程的程序设计面向对象的程序设计vs.7.1面向对象的程序设计3面向过程的程序设计方法:定义一个函数f1求三角形的周长。三角形的数据通过函数的参数传入;再定义一个函数f2求三角形的面积,三角形的数据同样通过函数的参数传入;在主函数中定义五组变量,分别表示五个三角形的基本数据;在主函数中利用每组变量分别调用函数f1和f2求得各三角形的周长和面积。每个三角形调用两次函数,共计调用10次函数;注意,函数调用时需正确使用参数。缺点:数据不能自成一体,数据和功能之间也没有必然的联系,程序显得有些凌乱。7.1面向对象的程序设计4面向对象的程序设计方法:由于5个三角形的变量表示,求三角形的周长和面积的方法均可以设计得完全一样,所以,在程序中可以定义一个通用的“模块”(称之为类),该类中描述了三角形的数据及求三角形的周长和面积的方法;在主函数中根据上面定义的类,定义五个“变量”(这五个所谓的变量称之为对象,其中不但包含了三角形的数据,还包含了对这些数据的使用“方法”---求周长和面积);调用各个对象的方法(求周长和面积的方法)即可直接得得到各个三角形的周长或面积。优点:由于表示各个三角形的对象之间相对独立,并且又自成一体,所以各个三菜形的数据不会混淆;同时,如果程序需要调整,可以直接在通用模板(类)中修改。7.1面向对象的程序设计5面向对象的程序是以类为模板,以对象为中心的程序结构。程序的功能体现在对象的方法上。7.2类与对象6类是对某一类问题的抽象的描述。某一类问题:在所关注的问题上是通用的;抽象:只提取必要的信息。1.类7.2类与对象7类的定义格式: class类名{ public:
公有成员列表; protected:
保护成员列表; private:
私有成员列表; };7.2类与对象8classA{
inta,b;protected: intc;public: voidset(intm,intn){ a=m; b=n; c=m+n; }voidprint(){cout<<a<<’\t’<<b<<’\t’<<c<<endl;}};7.2类与对象9几点说明:(1)类的缺省访问特性是私有的;
(2)保护的访问特性一般用于类的继承和派生;(3)访问特性关键字出现的顺序和次数均没有限制,但同
一访问特性成员应相对集中以增加程序的可读性。(4)不能用关键字auto、register、extern来将成员说明为
自动类型、寄存器类型或外部类型。可以用关键字
static将数据成员说明为静态类型的,其意义为该成员
属于类的所有对象所共有。(5)不能在类的定义过程中给成员变量赋初值。
(6)在类体内定义的函数具有内联特性。在类体外定义函数
时应说明函数的作用域classB{inta=20;
//错误,不能在类的定义过程中给其成员赋值public:voidset(inta);voidprint();};*7.2类与对象说明成员函数的两种方式:1.类中直接定义2.类中说明类体之外定义:类体内说明成员函数的一般格式为:
函数类型成员函数名(形参列表);类体外定义成员函数的一般格式为:
函数类型类名::成员函数名(形参列表) {
函数体 }*7.2类与对象classA{inta,b;protected:intc;public:intd;voidset(int,int,int); //函数原型说明voidprint(); //函数原型说明};*voidA::set(intm,intn,intk)//A { a=m; b=n; c=m+n; d=k; }voidA::print(){cout<<a<<'\t'<<b<<'\t'<<c<<'\t'<<d<<endl;}//B7.2类与对象132对象
对象是类概念下的实例。类是对某一类问题的通用的描述。只有对象才能表示具体的问题。类与对象的关系,类似于数据类型与变量的关系。定义对象的一般格式为:
类名对象名1,对象名2,…,对象名n;
例如: Aa1; Aa2,a3;通过对象名访问其数据成员的格式如下:
对象名.成员名访问成员函数的格如下:
对象名.成员函数名(实参列表)*7.2类与对象例如,可以通过已定义的对象a1、a2和a2来访问类A的公有成员: a1.set(1,2,0); //A a2.set(0,0,0); //B a3.set(5,5,0); //C a1.d=10; //D a1.print(); //E a2.print(); //F a3.print(); //G注意:访问成员函数时需要根据成员函数的形参提供相应的实参。*7.2类与对象7.2类与对象16#include<iostream.h>classB{inta,b;public:voidset(intt1,intt2){a=t1;b=t2;}voidprint(){cout<<a<<','<<b<<endl;}};voidmain(){ Bb1;
B&b2=b1;
B*pb; b1.set(5,10); b1.print(); b2.print();
pb=newB;
pb->set(20,40);
(*pb).print();
deletepb;}1)对象的指针、引用、动态对象;
2)同类型对象的相互赋值;
3)用指针操作对象成员的形式。类的对象之间也可以相互赋值,但这种赋值通常只限于同一个类的对象之间,并且成员未使用动态内存。对象之间赋值时,系统将对象的所有数据成员逐个进行拷贝。如果二个对象不是由同一个类定义的,即使其数据成员组成相同也不可以相互赋值。(此时,本质上属于两种不同形式的变量)当类中存在指针成员,并且这些指针成员指向动态内存时,如果仍需要实现对象间的赋值,在定义类时应当为类重新定义赋值运算符重载函数(了解)。*7.2类与对象#include<iostream.h>classC{inta,b,c;public:voidset(intt1,intt2,intt3){a=t1;b=t2;c=t3;}voidprint(){cout<<a<<'\t'<<b<<'\t'<<c<<endl;}};*7.2类与对象voidmain(){ Cc1,c2; c1.set(1,2,3); c2.set(0,0,0); cout<<"赋值前:\n"; c1.print(); c2.print();
c2=c1;//A cout<<"赋值后:\n"; c1.print(); c2.print();}例:类中成员的访问权限classF{inta,b;public:voidset(intt1,intt2){a=t1;b=t2;}voidprint(){charop=(b>=0?‘+’:‘-’);cout<<a<<op<<abs(b)<<“i”<<endl;//字符“i”为复数的虚部标记}intgeta(){returna;}intgetb(){returnb;}};*7.2类与对象voidmain(){ Ff1,f2,f3; f1.set(1,2);//A f1.print();//B f2.set(3,-4);//C f2.print();//D
inta1,b1;//局部变量 a1=f1.geta()+f2.geta(); b1=f1.getb()+f2.getb(); f3.set(a1,b1);//G f3.print();//H}a1=f1.a+f2.a;b1=f1.b+f2.b;//错误,不能在类体之外访问私有成员关于构造函数的说明:(1)构造函数是类的成员函数,并且与类同名。(2)构造函数没有函数类型,前面也不能加void。
函数体中也不能使用return语句返回函数值。(3)一般应将构造函数说明为公有的访问特性。(4)一个类可以有多个构造函数,但必须满足函数
重载的原则。(5)构造函数可以在类体内定义,也可以在类体外
定义。*7.3构造函数与析构函数classA{inta,b;public:A(int,int);};A::A(intm,intn){a=m;b=n;}7.3构造函数与析构函数211.构造函数#include<iostream.h>classB{inta,b;public:
B(intt1,intt2){a=t1;b=t2;}voidprint(){cout<<a<<','<<b<<endl;}};voidmain(){
Bb1(1,2),b2(5,10);b1.print();b2.print();}1)构造函数的形式、作用;
2)定义对象时必定调用构造函数;
3)构造函数一般是公有的。定义对象时提供的参数应与构造函数相匹配。7.3构造函数与析构函数22#include<iostream.h>
classA{//系统自动生成构造函数
inta;
public:
voidprint(){cout<<a;}};
classB{
inta;
public:
//用户定义了无参构造函数
B(){a=0;}
voidprint(){cout<<a;}};
classC{//类C中无缺省构造函数
inta;
public:
C(intt1){a=t1;}voidprint(){cout<<a;}
};classD{
inta;
public://用户定义的构造函数均有缺省值
D(intt1=0) {a=t1;}
voidprint(){cout<<a;}};
voidmain(){Aa1;//a1成员没有始化Bb1;//b1成员初始化为0Cc1;//出错
Dd1,d2(0); }缺省构造函数的3种情形:
1)没有参数或参数均有缺省值;
2)可以由系统系统自动生成;3)每个类最多只有一个;1、构造函数可以用根据已有的对象生成新对象。实现该功能的构造函数称为拷贝构造函数。*4、拷贝功能构造函数通常不需要定义,但在以下情况下必须重新定义:只把已建立对象的部分成员赋给新建对象;数据成员含有指针,并使用了动态内存。2、拷贝功能构造函数的使用。其格式有两种:
类类型新对象=已建立的对象;
或类类型新对象(已建立的对象);7.3构造函数与析构函数3、拷贝功能构造函数的定义。若用户不定义拷贝功能构造函数,系统自动产生一个缺省的拷贝功能构造函数,它把已建立对象各成员的值依次赋给新对象。其定义格式为:
类名::类名(类名&对象名){函数体
}
7.3构造函数与析构函数24#include<iostream.h>
classA{
inta;
public:
A(intt){a=t;}
voidprint(){cout<<a;}};
classB{
int*p;
public:
B(intt){a=newint(t);}
B(B&t)
{a=newint(*t.p);}
voidprint(){cout<<*p;}
voiddel(){deletep;}};
voidmain(){
Aa1(1),a2(a1);
Bb1(5),b2(b1);a1.print();
a2.print();b1.print();
b2.print();
b1.del();
b2.del();}7.3构造函数与析构函数25#include<iostream.h>classM{ inta;public: M(intt) {a=t;} intgeta() {returna;}};
classN{ inta,b,&c;
Mm1;//对象成员public:
N(intt):m1(++t),a(++t),c(a)
{b=2*t;}voidprint()
{cout<<m1.geta()<<a<<b<<c<<d<<endl;}
};voidmain(){
Nn1(1);n1.print();
//输出:3262}初始化成员列表:1)常量成员、引用和对象成员只
能采用成员列表的形式初始化;
2)列表只决定形式,不决定顺序。262.析构函数析构函数也是类的一种特殊成员函数,它执行与构造函数相反的操作,用于撤销对象时的一些清理工作,如释放分配给对象的内在空间等。每个类有且只有一个析构函数。如果用户没有为类定义析构函数,则系统为类生成一个空的析构函数。当用户定义了析构函数时,系统就不再生成缺省的析构函数。7.3构造函数与析构函数7.3构造函数与析构函数27#include<iostream.h>classA{
int*p;public:A(intt){p=newint(t);cout<<"A()-"<<*p<<endl;}
~A(){cout<<"~A()-"<<*p<<endl;deletep;}};析构函数调用顺序与构造函数的调用顺序相反
classB{inta;public:B(intt){a=t;}};voidmain(){Aa1(1),a2(2);Bb1(1),b2(2);}A(1)
A(2)
B(1)B(2)~B()~B()
~A()
~A()程序输出
A()-1A()-2~A()-2~A()-1*析构函数不可以提供参数,因而不可以重载;
如果不给类定义析构函数,则系统自动生成一个空的析构函数。因此,每个类有且只有一个析构函数。classA{inta,b;public:A(intm,intn){a=m;b=n;}};编译后
classA{inta,b;public:A(intm,intn){a=m;b=n;}~A(){}};7.3构造函数与析构函数#include<iostream.h>#include<string.h>classK{
char*s;public:
K(char*p){ intn=strlen(p); s=newchar[n+1]; strcpy(s,p);
}*7.3构造函数与析构函数K(K&t) { intn=strlen(t.s);
s=newchar[n+1]; strcpy(s,t.s); }
~K(){delete[]s;} voidprint(){ cout<<s<<endl; }};voidmain(){
Kk1("VisualC++Program.");
k1.print();
Kk2(k1); k2.print();}当成员数据为指针类型时,在构造函数中必须使用new运算符动态申请内存空间,为实现相同类型对象的拷贝,拷贝构造函数也必须显示定义;同时必须显式地定义析构函数,并在析构函数中使用delete运算符释放动态申请的内存空间。*每一个类均有一个或多个构造函数;每一个类均有且只有一个析构函数;构造函数用于初始化对象,由系统自动调用;析构函数清理对象时由系统调用;7.3构造函数与析构函数2026/10/14江苏科技大学电子信息学院计算机基础教学部31(1)数据成员为一维数组的构造函数。[题目]定义一个求一维数组平均值的类Array,具体要求如下:私有数据成员:inta[10]; //存储一维数组floataverage; //一维数组的平均值公有函数成员:构造函数Array(intt[],intn):初始化数据成员a;功能函数voidf():求一维数组的平均值;功能函数voidprint():输出数据成员。类的测试。在主函数中定义类Array的对象arr,并用数据{1,2,3,4,5,6,7,8,9,10}对定义的类进行测试。补充:成员数据为数组的构造函数2026/10/14江苏科技大学电子信息学院计算机基础教学部32算法分析:程序结构,面向对象的编程有两部分组成:类的定义;类的测试:主函数中用定义的类说明对象,然后通过对象调用有关的成员函数。构造函数:根据数据成员的具体情况,用形参初始化数据成员。本题中的数据成员为一维数据,应该用循环语句把形参中的元素逐个地赋值给数据成员。测试时,通常应该在主函数中定义一个一维数组,其值为测试数据,然后以该数组名作参数建立对象,最后通过对象调用相关的成员函数完成测试。调用成员函数时注意:调用格式为:对象.成员函数(实参);注意成员函数调用的顺序和参数。补充:成员数据为数组的构造函数2026/10/14江苏科技大学电子信息学院计算机基础教学部33编程实现(类的定义):classArray{
inta[10];
floataverage;public:
Array(intt[],intn){for(inti=0;i<n;i++)a[i]=t[i];} voidf(){
average=0; //A
for(inti=0;i<10;i++)average+=a[i];//B
average/=10;
}
voidprint(){
for(inti=0;i<10;i++)cout<<a[i]<<‘\t’;
cout<<“\naverage=”<<average<<‘\n’;
}};补充:成员数据为数组的构造函数程序解读:
能否把构造函数的函数体改为:
a=t;
能否把A行改为:intaverage=0;
把B行改为:for(inti=0;i<10;i++)average+=t[i];原因:a和t是数组名,为地址常量2026/10/14江苏科技大学电子信息学院计算机基础教学部34编程实现(主函数,测试类):voidmain()
{
intb[10]={1,2,3,4,5,6,7,8,9,10};
Arrayarr(b,10); //B
arr.f(); //C
arr.print(); //D
}
程序解读:
(1)能否不定义数组b,而把B行改为?
Arrayarr({1,2,3,4,5,6,7,8,9,10},10);(2)能否直接调用成员函数,即把C行改为“f();”?(3)能否把C行和D行的位置互换?补充:成员数据为数组的构造函数2026/10/14江苏科技大学电子信息学院计算机基础教学部35(2)数据成员为二维数组的构造函数 二维数组作类的数据成员时,其构造函数与一维数组相似,所不同的是:要通过嵌套的循环初始化数据成员。(3)数据成员为字符数组的构造函数。
字符数组作数据成员,与其他类型数组的主要区别表现在:构造函数中,对数据成员的初始化是通过字符拷贝函数完成的,具体为:strcpy(数据成员,形参);建立对象时,实参既可以是已定义的字符数组,也可以是一个字符串。补充:成员数据为数组的构造函数2026/10/14江苏科技大学电子信息学院计算机基础教学部36[题目]定义一个比较字符串大小的类String,具体要求如下:私有数据成员:chars1[20]; //存储字符串1chars2[20]; //存储字符串1intresult; //比较结果公有函数成员:构造函数String(char*p1,char*p2):用p1初始化s1,用p2初始化s2;功能函数intf():求比较结果;功能函数voidprint():输出字符串。类的测试。在主函数中定义类String的对象str,用数据“abcd”、“abc”对定义的类进行测试,并输出比较结果。补充:成员数据为数组的构造函数2026/10/14江苏科技大学电子信息学院计算机基础教学部37编程实现:classString{
chars1[20];
chars2[20];
intresult;
public:
String(char*p1,char*p2){strcpy(s1,p1);strcpy(s2,p2);} intf(){result=strcmp(s1,s2);returnresult;}
voidprint(){ cout<<s1<<‘\n’<<s2<<‘\n’; }
};voidmain()
{ chart[]=“abcd”;
Stringstr(t,“abc”);
str.print();
cout<<str.f()<<‘\n’;
}补充:成员数据为数组的构造函数(2)建立对象时,注意对象的参数(实参)应与构造函数的参数(形参)保持一致,否则不能产生对象;(3)注意成员函数的调用方式。程序解读:
(1)构造函数的参数能否改为?
charp1[],charp2[]可以。形参可以不给出数组长度2026/10/14江苏科技大学电子信息学院计算机基础教学部38用new运算符建立动态对象时,可用构造函数完成对象的初始化。如:Point*p=newPoint(3,9);当类的数据成员为指针时,在构造函数中应先用new动态分配空间,然后再对指针所指空间(分配的动态空间)赋值。切忌:对指针直接赋值;不为指针分配动态空间,而对指针所指空间赋值;虽然为指针分配了动态空间,却对指针赋值。设类A的数据成员为“int*p;”,以下构造函数都错误的:A(int*t){p=t;} //p表示具有10个元素的数组A(int*t){*p=*t;}A(int*t){for(inti=0;i<10;i++)p[i]=t[i];}A(int*t){p=newint[10];p=t;}//*p=*t;正确的应为:A(int*t){p=newint[10];
for(inti=0;i<10;i++)p[i]=t[i];}补充:new运算符与构造函数
2026/10/14江苏科技大学电子信息学院计算机基础教学部39字符型指针(字符数组)的初始化:
classString{
char*str;
public:
String(char*p){
if(p){str=newchar[strlen(p)+1];strcpy(str,p);}
elsestr=0;
}
voidprint(){cout<<str<<'\n';}
};voidmain()
{ Strings("Thisisabook.");
s.print();
}
补充:new运算符与构造函数
2026/10/14江苏科技大学电子信息学院计算机基础教学部40指向一维数组的指针(二维数组)的初始化:
classARRAY{
float(*p)[5];
introw;public:
ARRAY(floatt[][5],intn){ row=n;
p=newfloat[row][5]; for(inti=0;i<row;i++)//A
for(intj=0;j<5;j++)p[i][j]=t[i][j];
} voidprint(){for(inti=0;i<row;i++){//B
for(intj=0;j<5;j++)cout<<p[i][j]<<‘\t’;
cout<<‘n’; }
}
};补充:new运算符与构造函数(选学)
voidmain(){ floata[4][5]={1,2,…,20};
ARRAYarr(a,4); a.print();}程序解读:能否把A行和B行的row改成n?2026/10/14江苏科技大学电子信息学院计算机基础教学部41当用new运算符动态创建对象数组时,自动多次调用构造函数。如:Point*elems=newPoint[10];
//A
调用10次构造函数,产生10个对象;类Point必须具有缺省的构造函数。在定义对象数组时,可在初始化列表中调用构造函数对每个元素进行初始化。如:
classPoint{
public: intx,y;
Point(inta,intb){x=a;y=b;}
};
voidmain(){Pointp,*p1=&p,*p2[4];
PointP[4]={Point(1,3),Point(3,6),Point(9,2),Point(5,3)};
}补充:对象数组与构造函数(选学)
程序解读:
程序中一共产生了几个对象,调用了几次构造函数?
要在主函数中,增加A行的语句,程序应作怎样的修改?=0=1Point(){x=1;y=2;}7.4this指针42问题:
类的各对象的数据相互独立,但类的成员函数代码相同。成员函数如何区分其操作的数据所属的对象?
this指针是由系统提供的指向当前对象的指针;this指针一般由系统自动施加于类的非静态成员,也可以由用户显式使用。7.4this指针43#include<iostream.h>classA{inta,b;public:A(intt1,intt2){a=t1;b=t2;}
Aadd(inta,A&t)){
this->a=this->a+a+t.a;//A b=b+a+t.b;
//B该行语句等价于 //
this->b=this->b+a+t.b;
return*this;}voidprint(){cout<<a<<'\t'<<b<<endl;}};voidmain(){Aa1(1,2),a2(0,0);a1.print();a2.print();a1=a2.add(5,a1);a1.print();a2.print();}程序运行结果1 20 06 76 77.5静态成员44同一类的不同对象的同名成员可以有不同的数据。但是,在类的定义中用关键字static说明的静态成员为类的所有对象所共享。类的数据成员和成员函数均可以声明为静态的。7.5静态成员451.静态数据成员类的静态数据成员为类的所有对象所共享,即如果改变了其中一个对象的某个静态数据成员,则所有其他对象的相应的静态数据成员的值均随之改变。不同于普通数据成员,类的静态数据成员有着单独的存储空间(独立于特定的对象之外),所以在类的定义时必须在类体外单独定义其静态数据成员。类体中静态数据成员引用性说明的一般格式为:
static
数据类型静态数据成员名;类体外静态数据成员定义性说明的一般格式为:
类型名类名::静态数据成员名(初始值);
或
类型名类名::静态数据成员名=初始值;*7.5静态成员7.5静态成员47#include<iostream.h>classR{inta;staticintb,c;//引用性说明public:R(intt){a=t;}voidadd(){a++;b++;c++;}voidprint(){cout<<a<<'\t';cout<<b<<'\t'<<R::c<<endl;}};intR::b,R::c=5;//定义性说明voidmain(){Rr1(0),r2(3);r1.print();r2.print();r1.add(); r1.print();r2.print();}程序输出:0 0 53 0 51 1 63 1 6*例题说明:A行的说明仅为引用性说明,在类体外C行对这两个成员变量的定义性说明是必须的。注意,类体外给出类的静态成员的定义性说明时不可以再使用static关键字,但必须使用作用域运算符“
::”说明其作用域,即其所属的类。7.5静态成员7.5静态成员492.静态成员函数用关键字static修饰的函数为类的静态成员函数。静态成员函数内部没有this指针,不能直接访问类的非静态成员,只能直接访问类的静态成员。静态成员函数属于整个类,是该类的所有对象所共有的成员函数。7.5静态成员50#include<iostream.h>classS{inta;staticintb;//静态成员数据public:S(intt){a=t;}
staticvoidadd1()//静态成员函数{a++;//出错!b++;}
staticvoidadd2(St)//静态成员函数{t.a++;
b++;}voidprint(){cout<<a<<'\t'<<b<<endl;}};intS::b=5;voidmain(){S::add1();
Ss1(0);s1.print();s1.add2(s1);s1.print();}删除出错语句后的程序输出为:0 60 77.6常成员与常对象51如果在定义类或声明类的对象时用关键字“const”修饰类的成员或对象,则这些类的成员或对象被说明为常成员或常对象,它们在程序运行期间不能被改变或不能改变对象的成员。7.6常成员与常对象521.常数据成员#include<iostream.h>classT{
inta,&b;constintc; //或intconstc;conststaticintd;//或staticconstintd;public:T(intt1,intt2):b(a),c(t1){a=t2;}voidprint(){cout<<a<<b<<c<<d<<endl;}voidfun(){a++;b++; }};constintT::d=15;voidmain(){Tt(5,10);t.print();t.fun();t.print();}常数据成员只能被读取,不能被改变。普通常数据成员只能通过列表初始化静态常数据成员只能定义时初始化程序的输出为:101051512125157.6常成员与常对象532.常成员函数常成员函数的定义形式:
类型
函数名(参数表)const;关键字const加在函数头部的最后,而不是加在最前面。常成员函数原形说明和定义时该关键字均不可省略。常成员函数不能修改本类的数据成员,也不能调用其他非常成员函数。关键字const可以和函数参数表一样作为函数重载时区分不同函数的标志。在这种情况下,重载的原则是:常对象调用常成员函数,一般对象调用一般成员函数。7.6常成员与常对象543.常对象常对象的说明与普通常变量的定义相类似:
类名
const
对象名;
或:
const
类名对象名;常对象定义时必须初始化,且一旦定义,则不能被改变;通过常对象只能调用常成员函数;普通成员函数调用一般成员函数。7.6常成员与常对象55#include<iostream.h>classW{inta;intconstb;public:W(intt1,intt2):b(t1){a=t2;}voidprint()const{f1(5);cout<<a+b<<endl;}voidprint(){f1(5);
cout<<a+b<<endl;}
voidf1(intt){a+=t;}
voidf1(intt)const{cout<<t<<endl;}};voidmain(){
constWw1(5,10);Ww2(5,10);
w1.print();w2.print();}程序输出:51520*程序分析:两个print函数和两个f1函数分别构成两对重载函数;普通成员函数print调用的f1函数与常成员函数print调用的f1函数不同;
主函数中w1是常对象,通过它调用的print函数是常成员函数;主函数中w2不是常对象,通过它调用的print函数是普通成员函数;7.6常成员与常对象7.8习题571.下列有关构造函数的叙述中,正确的是
。A.类的构造函数不能重载B.任何一个类必定有构造函数C.可以定义没有构造函数的类
D.任何一个类必定有一个缺省的构造函数2.对类的析构函数的叙述中,正确的是
。A.析构函数完成类的初始化B.析构函数完成对象的初始化C.
析构函数完成撤消对象D.析构函数和成员函数一样可以显式地调用BC【例7-17】定义一个类,将一组数据按给定的行列表示成一个二维数组。#include<iostream.h>classArray{
int*p;
//p指向数组起始元素,构造函数中应初始化指针成员
intm,n;//m、n分别为二维数组的行数和列数public:
Array(int*t,inta,intb){
m=a; n=b; p=newint[m*n];//初始化指针成员
for(inti=0;i<m*n;i++) *(p+i)=*(t+i); }
~Array(){delete[]p;}//撤销动态内存*7.7程序举例intget(inti,intj)//取数组行下标为i,列下标为j的元素 { return*(p+i*n+j); }//Avoidprint(){ for(inti=0;i<m;i++){ for(intj=0;j<n;j++) cout<<get(i,j)<<'\t'; cout<<'\n'; } }};*7.7程序举例voidmain(){ int*data,i0,j0; cout<<"请输入二维数组的行数和列数:"; cin>>i0>>j0; data=newint[i0*j0]; cout<<"请输入数组元素:"; for(inti=0;i<i0;i++) for(intj=0;j<j0;j++) cin>>*(data+i*j0+j);//B
Arraya1(data,i0,j0); a1.print(); delete[]data;}*7.7程序举例7.8习题614.试定义一个类STR,将字符串中的数字字符依次全部移到字符串的后半部。具体要求如下:(1)私有数据成员char*p;p为待处理的字符串。(2)公有成员函数STR(char*s);构造函数,用s初始化数据成员p。voidmove(char&t1,char&t2);交换两个字符的位置。voidfun();根据题意处理字符串p。算法要求:从左到右依次对字符串p的每个字符进行检测,如果在数字字符的右侧有非数字字符,则通过调用函数move()将该非数字字符与前一个字符进行交换,直到前一个字符为非数字字符为止。~STR();析构函数,撤销所占用的动态存储空间。voidprint();输出数组中的所有元素。(3)在主函数中对类STR进行测试。7.8习题62voidSTR::fun(){for(char*p1=p;*p1;p1++){if(*p1>'9'&&*p1<'0')continue;char*p2=p1;while(*p2>='0'&&*p2<='9')p2++;//p2后移至非数字字符
if(!(*p2))break;while(*p2&&p2>p1){move(*p2,*(p2-1));p2--;}//p2所指向的非数字字冒泡前移
}}voidmain(){chars[]="1ab23cd4ef56g";STRtest(s);
test.print();test.fun();test.print();}#include<iostream.h>#include<string.h>classSTR{char*p;public:STR(char*s){p=newchar[strlen(s)+1];strcpy(p,s);}voidfun();voidmove(char&t1,char&t2){chart=t1;t1=t2;t2=t;}voidprint(){cout<<p<<endl;}~STR(){delete[]p; }};7.8习题635.试定义一个类Array,将二维数组的各列依次循环右移n次。具体要求如下:(1)私有数据成员inta[4][4];待处理的数组。(2)公有成员函数Array(intt[][4],intn);构造函数,用数组t初始化数组a,n表示数组的行数。voidright();将数组a各列循环右移1次,其中,数组的最右一列移至数组的最左边。voidrmove(intn);利用成员函数right()将数组a的各列循环右移n次。voidprint();输出数组a。
(3)在主函数中定义一个二维数组对类Array进行测试。*7.8习题#include<iostream.h>classArray{inta[4][4];public:Array(int[][4],int);voidright();voidremove(intn){for(intk=0;k<n;k++)right();}voidprint(){for(inti=0;i<4;i++){for(intj=0;j<4;j++)cout<<a[i][j]<<'\t';cout<<'\n';} }};Array::Array(intt[][4],intn){for(inti=0;i<n;i++)for(intj=0;j<4;j++)a[i][j]=t[i][j];}voidArray::right()//各行循环右移一次{for(inti=0;i<4;i++){intt=a[i][3];for(intj=3;j>0;j--)a[i][j]=a[i][j-1];a[i][0]=t;}}*voidmain(){ intb[4][4]={{1,5,9,13},{2,6,10,14},{3,7,11,15},{4,8,12,16}};
Arraytest(b,4); test.print(); cout<<endl;
test.remove(2); test.print(); cout<<endl;}7.8习题7.8习题666.对一个5位数的任意整数,求出其降序数。例如:整数是82319,则其降序数是98321。算法提示:将整数的各位数分解到一维整型数组a中,再将a数组中的元素按降序排序,最后输出a数组元素值。试建立一个类NUM,用于完成该功能。具体要求如下:(1)私有数据成员intn;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年云南省蒙自市高三物理下册期末考试模拟试卷及答案
- 2026年山西省原平市高一历史上册期末考试自测卷含答案
- 洛宁县2025年数学三年级第二学期期末联考试题含答案
- 保健砭术师安全生产规范考核试卷含答案
- 一次雷达机务员岗前工作改进考核试卷含答案
- 金属制粉工岗前技能综合实践考核试卷含答案
- 煤间接液化合成操作工测试验证水平考核试卷含答案
- 黄酒灌装工岗前实操知识技能考核试卷含答案
- 冷链食品安全管理员岗中设备维护考核试卷含答案
- 钢琴及键盘乐器制作工常识能力考核试卷含答案
- 2027年初中八年级心理健康《绽放自信的花朵》教学设计
- 高中生物高三一轮复习教学设计:植物生长素与其他植物激素核心考点突破
- 2026年最高人民检察院招聘书记员考试试题及答案
- 高中物理选择性必修第三册《气体的状态》教学设计
- 地震勘探平原地区安全作业培训
- 既有建筑外立面改造施工技术方案
- 木作文物修复师岗位实践理论考核试卷含答案
- (2026年秋)人教版八年级地理上册知识点大全(2024修订版)
- 吊篮施工专项方案及吊篮安全操作方案
- 【答案】《人工智能与创新》(南开大学)章节期末中国大学慕课答案
- 国民经济-烟草种植行业(2025年)分析报告
评论
0/150
提交评论