计算机二级考试C++复习资料类的其他几点问题Word格式.docx
《计算机二级考试C++复习资料类的其他几点问题Word格式.docx》由会员分享,可在线阅读,更多相关《计算机二级考试C++复习资料类的其他几点问题Word格式.docx(9页珍藏版)》请在冰豆网上搜索。
intmo,da,yr;
char*month;
public:
Date(intm=0,intd=0,inty=0);
Date(constDate&
);
~Date();
voiddisplay()const;
};
Date:
:
Date(intm,intd,inty)
staticchar*mos[]=
January,February,March,April,May,June,
July,August,September,October,November,December
mo=m;
da=d;
yr=y;
if(m!
=0)
month=newchar[strlen(mos[m-1])+1];
strcpy(month,mos[m-1]);
}
else
month=0;
Date(constDate&
dt)
mo=dt.mo;
da=dt.da;
yr=dt.yr;
if(dt.month!
month=newchar[strlen(dt.month)+1];
strcpy(month,dt.month);
~Date()
delete[]month;
voidDate:
display()const
if(month!
cout<
<
month<
'
'
da<
<
yr<
std:
endl;
intmain()
Datebirthday(6,24,1940);
birthday.display();
Datenewday=birthday;
newday.display();
Datelastday(birthday);
lastday.display();
return0;
本例中,用到了两次拷贝构造函数。
一个是使用普通的C++初始化变量的语句:
另一个是使用构造函数的调用约定,即把初始化值作为函数的参数:
二、类的引用
在函数参数和返回值中,如果一定要使用传值方式,那么使用类对象的引用,是一个提升效率的方法。
类的数据成员也能够是一个引用,但必须注意:
第一,一个引用必须初始化。
通常一个类对象并不会像结构那样用大括号来初始化,而是调用构造函数。
所以在构造函数里必须初始化类当中的引用成员。
第二,引用是一个别名。
即使类里面的引用在使用方式上看起来和类的一般数据成员没有什么区别,但是作用在其上的操作,实际上是对用来初始化它的那么对象实行的。
intda,mo,yr;
Date(intd,intm,inty)
{da=d;
mo=m;
}
voidDisplay()const
{cout<
/'
<
mo<
yr;
classTime
inthr,min,sec;
Time(inth,intm,ints)
{hr=h;
min=m;
sec=s;
hr<
min<
sec;
classDateTime
constDate&
dt;
constTime&
tm;
DateTime(constDate&
d,constTime&
t):
dt(d),tm(t)
//empty
dt.Display();
;
tm.Display();
Datetoday(7,4,2004);
Timenow(15,20,0);
DateTimedtm(today,now);
dtm.Display();
我们来看看这个程序中DateTime的构造函数的格式:
冒号操作符引出了一个参数初始化表。
必须使用这种格式来初始化引用数据成员,而不能够在函数体内来实行初始化工作。
如果构造函数像上例一样不是内联的,那么不要在类声明中构造函数的原型上使用冒号和初始化值表,而是像下面这样,把参数初始化表放在定义构造函数的地方:
ClassDateTime
d,constTime&
t);
DateTime:
DateTime(constDate&
t):
dt(d),tm(t)
能够使用构造函数的参数初始化表来初始化任何数据成员。
特别是常量数据成员,和引用一样,只能在参数初始化表里实行初始化,这是因为不能够在构造函数内部为常量数据成员赋值。
当一个类含有引用数据成员时,一旦引用被实例化和初始化以后,就无法修改它的值,所以该类不可能彻底地重载赋值运算符函数。
三、构造函数的参数初始化表
如果类对象的某些数据成员没有载构造函数内部被初始化,那么必须使用构造函数的参数初始化表对他们实行初始化。
否则,编译器不止到该如何初始化这些还等着在构造函数内部赋值的成员。
我们习惯用参数初始化表来初始化所有数据成员。
intmo,da,yr;
Date(intm=0,intd=0,inty=0);
classEmployee
intempno;
Datedatehired;
Employee(inten,Date&
dh);
能够用下面两种方法编写Employee类的构造函数:
Employee:
Employee(inten,Date&
empno=en;
datehired=dh;
或者;
dt):
empno(en),datehired(dh)
虽然这两种方法效果是一样的,但是根据Date对象默认构造函数的复杂性的不同,这两种形式的效率差别是很大的。
四、对const修饰符的简单说明
如果一个对象被声明为常量,那么该对象就不能够调用类当中任何非常量型的成员函数(除了被编译器隐式调用的构造函数和析构函数)。
看下面的代码;
intmonth,day,year;
Date(intm,d,y):
month(m),day(d),year(y){}
voiddisplay()
constDatedt(4,7,2004);
dt.display();
//error
这个程序即使编译时没有问题,但运行时却出错了。
这是因为常量对象不能调用非常量函数。
编译器只看函数的声明,而不在乎函数的具体实现。
实际上函数的实现能够在程序中的任何地方,也能够是在另一个源代码文件中,这就超过了编译器的当前可见范围。
//date.h
Date(intm,d,y);
voiddisplay();
//date.cpp
#includedate.h
Date(intm,d,y):
display()
//program.cpp
#includedate.cpp
解决出错的问题有两个方法:
第一是声明display()函数为常量型的
//indate.h
voiddisplay()const
//intdate.cpp
另一个解决方式就是省略掉Date对象声明里的const修饰符。
Datedt(4,7,2004);
还有另一个容易出错的地方:
voidabc(constDate&
//error提示display没有const修饰符
函数abc()声明了一个Date对象的常量引用,这说明该函数不会修改传递进来的参数的值。
如果Date:
display()函数不是常量型的,那么在函数abc()里就不能调用它,因为编译器会认为Date:
display()函数有可能会修改常量的值。
不论类对象是否是常量型的,它必须修改某个数据成员的值时,ANSI委员会设立了mutable关键字。
五、可变的数据成员
假设需要统计某个对象出现的次数,不管它是否是常量。
那么类当中就应该有一个用来计数的整型数据成员。
只要用mutable修饰符来声明该数据成员,一个常量型的成员函数就能够修改它的值。
classAValue
intval;
mutableintrptct;
AValue(intv):
val(v),rptct(0){}
~AValue()
voidreport()const;
voidAValue:
report()const
rptct++;
val<
endl;
constAValueaval(123);
aval.report();