return0;
}
2.调试下列程序。
//sy3_2.cpp
#include
usingnamespacestd;
classTPoint
{
public:
TPoint(intx,inty){X=x;Y=y;}
TPoint(TPoint&p);
~TPoint(){cout<<"Destructoriscalled\n";}
intgetx(){returnX;}
intgety(){returnY;}
private:
intX,Y;
};
TPoint:
:
TPoint(TPoint&p)
{
X=p.X;
Y=p.Y;
cout<<"Copy-initializationConstructoriscalled\n";
}
intmain()
{
TPointp1(4,9);
TPointp2(p1);
TPointp3=p2;
cout<<"p3=("<return0;
}
在该程序中,将TPoint类的带有两个参数的构造函数进行修改,在函数体内增添下述语句:
cout<<"Constructoriscalled.\n";
(1)写出程序的输出结果,并解释输出结果。
(2)按下列要求进行调试:
在主函数体内,添加下列说明语句:
TPointP4,P5
(2);
调试程序会出现什么现象?
为什么?
如何解决?
(提示:
对已有的构造函数进行适当修改)结合运行结果分析如何使用不同的构造函数创建不同的对象。
3.请定义一个矩形类(Rectangle),私有数据成员为矩形的长度(len)和宽度(wid),无参构造函数置len和wid为0,有参构造函数置len和wid为对应形参的值,另外还包括求矩形周长、求矩形面积、取矩形长度和宽度、修改矩形长度和宽度为对应形参的值、输出矩形尺寸等公有成员函数。
要求输出矩形尺寸的格式为“length:
长度,width:
宽度”。
(sy3_3.cpp)
三、分析与讨论
1.类中私有成员的访问权限。
答:
私有成员是被隐藏的数据,只有该类的成员函数或友元函数才可以引用它.
2.构造函数与析构函数的调用顺序。
答:
构造函数的调用顺序与声明对象的顺序一致,而析构函数的调用顺序与构造函数的调用顺序正好相反。
实验四静态成员、友元
一、实验目的和要求
了解成员函数的特性、静态成员、友元等概念。
二、实验内容
1.调试下列程序,写出输出结果,并分析输出结果。
//sy4_1.cpp
#include
usingnamespacestd;
classMy
{
public:
My(intaa)
{ A=aa;
B-=aa;
}
staticvoidfun(Mym);
private:
intA;
staticintB;
};
voidMy:
:
fun(Mym)
{
cout<<"A="<cout<<"B="<
}
intMy:
:
B=100;
intmain()
{
MyP(6),Q(8);
My:
:
fun(P);
Q.fun(Q);
return0;
}
输出结果:
分析:
非静态数据成员从属于某个对象,而静态数据成员从属于整个类。
执行语句1调用构造函数,使得对象P,Q的数据成员A的值分别是6和8,因此fun( )中输出数据成员A的值分别是6和8。
数据成员B的值的初始值是100,执行语句1,创建对象P时,B的值改变为94,再创建对象Q时,B的又有被修改为86,因此fun( )中输出数据成员B的值都是86。
2.分析、调试程序,完成下列问题:
//sy4_2.cpp
#include
usingnamespacestd;
#include
classMy
{
public:
My(doublei=0){x=y=i;}
My(doublei,doublej){x=i;y=j;}
My(My&m){x=m.x;y=m.y;}
frienddoubledist(My&a,My&b);
private:
doublex,y;
};
doubledist(My&a,My&b)
{
doubledx=a.x-b.x;
doubledy=a.y-b.y;
returnsqrt(dx*dx+dy*dy);
}
intmain()
{
Myml,m2(15),m3(13,14);
Mym4(m3);
cout<<"Thedistance1:
"<cout<<"Thedistance2:
"<cout<<"Thedistance3:
"<cout<<"Thedistance4:
"<return0;
}
(1)指出所有的构造函数,它们本程序中分别起什么作用?
答:
类中共有3个构造函数
My(doublei=0);
My(doublei,doublej);
My(My&m);
第一个构造函数用来初始化对象m1和对象m2,第二个构造函数用来初始化对象m3,第三个是拷贝构造函数,用来初始化对象m4。
(2)指出设置默认参数的构造函数。
答:
类中设置默认参数的构造函数为
My(doublei=0);
(3)指出友元函数。
将友元函数放到私有部分,观察结果是否有变化。
答:
函数dist()为有元函数。
将其放到私有部分,编译程序发现结果仍然是正确的。
这是因为有元函数是一个在类里声明的普通函数,声明的位置可以在类的任何部位,既可以在public区,也可在protected区和private区,意义完全一样。
(4)写出输出结果,并分析输出结果。
结果分析:
友元函数dist()的主要作用是求两点之间的距离。
3.声明Book与Ruler两个类,二者都有weight属性,定义二者的一个友元函数totalWeight(),计算二者的重量和。
(sy4_3.cpp)
三、分析与讨论
1.如何定义静态数据成员和成员函数?
答:
静态成员是一种特殊的类成员,在类的范围内所有对象共享该数据。
静态成员包括静态数据成员和静态成员函数,其定义格式为:
static<静态成员的定义>;
2.如何对静态数据成员初始化?
答:
静态成员数据的初始化与一般数据成员不同,它的初始化不能在构造函数中进行。
静态数据成员初始化在类体外进行,其格式为:
<数据类型><类名>:
:
<静态数据成员名>=<初始值>;
3.静态成员函数中访问静态成员与非静态成员有何区别?
答:
由于静态成员函数没有this指针,它只能直接访问该类的静态数据成员,静态成员函数和类以外的函数和数据,访问类中的非静态数据成员必须通过参数传递方式得到对象名,然后通过对象名来访问。
4.如何调用静态成员函数?
答:
调用静态成员函数的格式为:
<类名>:
:
<静态成员函数名>(<参数表>);
5.如何理解“静态成员不是属于某个对象的,而是属于类的所有对象的。
”这句话?
答:
从实验内容的第1题的输出结果可以看出,无论是对象P还是对象Q修改静态成员B,都是对同一个B的修改。
可见静态成员B不是只属于对象P,也不是只属于对象Q,而是属于类的所有对象。
6.比较友元函数与一般函数在定义和调用方面的异同。
答:
与一般函数的定义不同,友元函数的声明在类中,并在前面加上关键字friend;但友元函数的调用形式与一般函数完全相同。
实验五继承与派生
一、实验目的和要求
1.掌握派生类的定义方法和派生类构造函数的定义方法。
2.掌握不同继承方式的情况下,基类成员在派生类中的访问权限。
二、实验内容
调试下列程序,并对程序进行修改后再调试,指出调试中的出错原因。
//
#include
usingnamespacestd;
classA
{
public:
voidseta(inti){a=i;}
intgeta(){returna;}
public:
inta;
};
classB:
publicA
{
public:
voidsetb(inti){b=i;}
intgetb(){returnb;}
voidshow(){cout<<"A:
:
a="<public:
intb;
};
intmain()
{
Bbb;
bb.seta(6);
bb.setb(3);
bb.show();
cout<<"A:
:
a="<cout<<"B:
:
b="<cout<<"A:
:
a="<cout<<"B:
:
b="<return0;
}
按下列要求对程序进行修改,然后调试,对出现的错误分析其原因。
(1)将派生类B的继承方式改为private时,会出现哪些错误和不正常现象?
为什么?
答:
将派生类B的继承方式改为private时,编译程序指出语句2,语句5和语句7有错。
这是因为当类的继承方式为私有继承时,基类A的公有成员函数a,公有成员函数seta()和geta()作为派生类B的私有成员,派生类的成员函数可以直接访问它们,但在类外部,派生类的对象无法访问它们。
(2)将派生类B的继承方式改为protected时,会出现哪些错误和不正常现象?
为什么?
答:
将派生类B的继承方式改为protected时,编译程序指出语句2,语句5和语句7有错。
这是因为当类的继承方式为保护继承时,基类A的公有数据成员a,公有成员函数seta()和geta()作为派生类B的保护成员,派生类的成员函数可以直接访问它们,但在类外部,派生类的对象无法访问它们。
(3)将派生类B的继承方式恢复为public后,再将类A中数据成员int型变量a的访问权限改为private时,会出现哪些错误和不正常现象?
为什么?
答:
将类A中数据成员int型变量
(4)派生类B的继承方式仍为public,将类A中数据成员int型变量a的访问权限改为protected时,会出现哪些错误和不正常现象?
为什么?
三、分析与讨论
通过对实验内容的调试,总结不同继承方式的情况下,基类成员在派生类中的访问权限。
实验六多态性与虚函数
一、实验目的和要求
了解静态联编和动态联编的概念。
掌握动态联编的条件。
二、实验内容
1.分析、调试下列程序
//sy6_1.cpp
#include
usingnamespacestd;
classPoint
{
public:
Point(doublei,doublej){x=i;y=j;}
doubleArea(){return0.0;}
private:
doublex,y;
};
classRectangle:
publicPoint
{
public:
Rectangle(doublei,doublej,doublek,doublel):
Point(i,j){w=k;h=l;}
doubleArea(){returnw*h;}
private:
doublew,h;
}:
intmain()
{
Pointp(3.5,7);
doubleA=p.Area();
cout<<"Area="<Rectangler(1.2,3,5,7.8);
A=r.Area();
cout<<"Area="<return0;
}
写出程序的输出结果,并解释输出结果。
2.分析、调试下列程序
//sy6_2.cpp
#include
usingnamespacestd;
constdoublePI=3.1415;
classShap
{
public:
virtualdoubleArea()=0;
};
classTriangle:
publicShap
{
public:
Triangle(doubleh,doublew){H=h;W=w;}
doubleArea(){return0.5*H*W;}
private:
doubleH,W;
};
classRectangle:
publicShap
{
public:
Rectangle(doubleh,doublew){H=h;W=w;}
doubleArea(){returnH*W;}
private:
doubleH,W;
};
classCircle:
publicShap
{
public:
Circle(doubler){R=r;}
doubleArea(){returnPI*R*R;}
private:
doubleR;
};
classSquare:
publicShap
{
public:
Square(doubles){S=s;}
doubleArea(){returnS*S;}
private:
doubleS;
};
doubleTotal(Shap*s[],intn)
{
doublesum=0;
for(inti