ThinkinginC++annotatedsolutionguidecharpter5.docx
《ThinkinginC++annotatedsolutionguidecharpter5.docx》由会员分享,可在线阅读,更多相关《ThinkinginC++annotatedsolutionguidecharpter5.docx(14页珍藏版)》请在冰豆网上搜索。
ThinkinginC++annotatedsolutionguidecharpter5
Chapter5
5-1
Createaclasswithpublic,private,andprotecteddatamembersandfunctionmembers.Createanobjectofthisclassandseewhatkindofcompilermessagesyougetwhenyoutrytoaccessalltheclassmembers.
(Lefttothereader)
5-2
WriteastructcalledLibthatcontainsthreestringobjectsa,b,andc.Inmain()createaLibobjectcalledxandassigntox.a,x.b,andx.c.Printoutthevalues.Nowreplacea,b,andcwithanarrayofstrings[3].Showthatyourcodeinmain()breaksasaresultofthechange.NowcreateaclasscalledLibc,withprivatestringobjectsa,b,andc,andmemberfunctionsseta(),geta(),setb(),getb(),setc(),andgetc()tosetandgetthevalues.Writemain()asbefore.Nowchangetheprivatestringobjectsa,b,andctoaprivatearrayofstrings[3].Showthatthecodeinmain()doesnotbreakasaresultofthechange.
(Lefttothereader)
5-3
Createaclassandaglobalfriendfunctionthatmanipulatestheprivatedataintheclass.
(Lefttothereader)
5-4
Writetwoclasses,eachofwhichhasamemberfunctionthattakesapointertoanobjectoftheotherclass.Createinstancesofbothobjectsinmain()andcalltheaforementionedmemberfunctionineachclass.
Solution:
//:
S05:
PointToMeAndYou.cpp
#include
usingnamespacestd;
classYou;//Forwarddeclaration
classMe{
public:
voidProcessYou(You*p){
cout<<"ProcessingYouat"<
}
};
classYou{
public:
voidProcessMe(Me*p){
cout<<"ProcessingMeat"<
}
};
intmain(){
Meme;
Youyou;
me.ProcessYou(&you);
you.ProcessMe(&me);
}
/*Output:
ProcessingYouat0065FDF4
ProcessingMeat0065FDFC
*/
///:
~
Whentwoclassesrefertoeachother,itisnecessarytoforward-declareatleastoneofthem,asIdidabove.Youmustonlyusepointers,ofcourse,oryou’lltrulyfindyourselfinachicken-and-eggfix.FYI:
whenclasseshavearelationship,forexample,andEmployee“has-a”Manager,itiscommontoreflectthisrelationshipbyactuallystoringapointertotheManagerobjectasamemberintheEmployeeobject,soyoudon’thavetoexplicitlypasspointersasargumentstomemberfunctionslikeIdidhere.
5-5
Createthreeclasses.Thefirstclasscontainsprivatedata,andgrantsfriendshiptotheentiresecondclassandtoamemberfunctionofthethirdclass.Inmain(),demonstratethatalloftheseworkcorrectly.
Solution:
//:
S05:
MyFriends.cpp
#include
usingnamespacestd;
classHasStuff;//MustprecedeGoodFrienddefinition
classGoodFriend{//MustprecedeHasStuffdefinition
public:
voidhasAccess(HasStuff*p);
voidhasNoAccess(HasStuff*p){
cout<<"Cannotaccess"<
}
};
classHasStuff{
private:
intx;
friendclassBestFriend;
friendvoidGoodFriend:
:
hasAccess(HasStuff*);
};
//MustfollowHasStuffdefinition:
voidGoodFriend:
:
hasAccess(HasStuff*p){
cout<<"FromGoodFriend:
:
hasAccess:
"<x<}
//AllmethodsofBestFriendhaveaccesstoHasStuff:
:
x
//ThismustalsofollowtheHasStuffdefinition:
classBestFriend{
public:
voidinitFriend(HasStuff*p){
p->x=5;
}
voidqueryFriend(HasStuff*p){
cout<<"FromBestFriend:
"<x<}
};
intmain(){
HasStuffh;
BestFriendb;
b.initFriend(&h);
b.queryFriend(&h);
GoodFriendg;
g.hasAccess(&h);
g.hasNoAccess(&h);
}
/*Output:
FromBestFriend:
5
FromGoodFriend:
:
hasAccess:
5
Cannotaccess0065FE00
*/
///:
~
Thisisanotherexerciseinforwarddeclarations.ThedefinitionofGoodFriendrequirestheexistenceofclassHasStuff,butIcannotincludetheimplementationofGoodFriend:
:
hasAccess()insitu,becauseitusesthefactthatHasStuffcontainsanintegernamedx(likewisefortheentireclassBestFriend).Also,ifyoutriedtoaccessHasStuff:
:
xinGoodFriend:
:
hasNoAccess()youwouldgetacompilererror.Thestatement“friendclassBestFriend”insideofHasStuffissimultaneouslyaforwarddeclarationandafrienddeclaration,otherwiseIwouldhavehadtoforward-declareBestFriendbeforethedefinitionofHasStuff(butI’mlazy).
5-6
CreateaHenclass.Insidethis,nestaNestclass.InsideNest,placeanEggclass.Eachclassshouldhaveadisplay()memberfunction.Inmain(),createaninstanceofeachclassandcallthedisplay()functionforeachone.
Solution:
//:
S05:
NestedFriends.cpp
#include
usingnamespacestd;
classHen{
public:
voiddisplay(){
cout<<"Hen:
:
display\n";
}
classNest{
public:
voiddisplay(){
cout<<"Hen:
:
Nest:
:
display\n";
}
classEgg{
public:
voiddisplay(){
cout<<"Hen:
:
Nest:
:
Egg:
:
display\n";
}
};
};
};
intmain(){
Henh;
Hen:
:
Nestn;
Hen:
:
Nest:
:
Egge;
h.display();
n.display();
e.display();
}
/*Output:
Hen:
:
display
Hen:
:
Nest:
:
display
Hen:
:
Nest:
:
Egg:
:
display
*/
///:
~
NestandEggarejustlikenormalclassesexcepttheyresideinthescopeofotherclassesinsteadoftheglobalscope,whichexplainstheneedfortheexplicitqualificationviathescoperesolutionoperator.Also,HenhasnoaccessrightstoanyprivatemembersofNestorEgg,nordoesNesthaveanyrightstoEgg’sprivatemembers(iftherewereany–seethenextexercise).
5-7
ModifyExercise6sothatNestandEggeachcontainprivatedata.Grantfriendshiptoallowtheenclosingclassesaccesstothisprivatedata.
Solution:
//:
S05:
NestedFriends.cpp
#include
usingnamespacestd;
classHen{
public:
classNest{
intx;
friendclassHen;
public:
classEgg{
inty;
friendclassNest;
public:
voiddisplay(){
cout<<"Hen:
:
Nest:
:
Egg:
:
display:
"<}
};
voidinitEgg(Egg*e){
e->y=2;
}
voiddisplay(){
cout<<"Hen:
:
Nest:
:
display:
"<}
};
voidinitNest(Nest*n){
n->x=1;
}
voiddisplay(){
cout<<"Hen:
:
display\n";
}
};
intmain(){
Henh;
Hen:
:
Nestn;
Hen:
:
Nest:
:
Egge;
h.initNest(&n);
n.initEgg(&e);
h.display();
n.display();
e.display();
}
/*Output:
Hen:
:
display
Hen:
:
Nest:
:
display:
1
Hen:
:
Nest:
:
Egg:
:
display:
2
*/
///:
~
InthisexampleIhadtomovetheimplementationofHen:
:
Nest:
:
display()pastthenestedclassEgg,becauseitaccessmembersofEgg.Thesamereasoningappliestotheinit-functionsabove.
5-8
Createaclasswithdatamembersdistributedamongnumerouspublic,private,andprotectedsections.AddamemberfunctionshowMap()thatprintsthenamesofeachofthesedatamembersandtheiraddresses.Ifpossible,compileandrunthisprogramonmorethanonecompilerand/orcomputerand/oroperatingsystemtoseeiftherearelayoutdifferencesintheobject.
Here’sasamplefortwoparticularcompilers:
Solution:
//:
S05:
MapMembers.cpp
#include
usingnamespacestd;
classMapped{
intx;
protected:
inty;
public:
intz;
voidshowMap(){
cout<<"xisat"<<&x<cout<<"yisat"<<&y<cout<<"zisat"<<&z<}
};
intmain(){
Mappedm;
m.showMap();
}
/*Output:
//CompilerA:
xisat0065FDF8
yisat0065FDFC
zisat0065FE00
//CompilerB:
xisat0064FDEC
yisat0064FDF0
zisat0064FDF4
*/
///:
~
5-9
CopytheimplementationandtestfilesforStashinChapter4sothatyoucancompileandtestStash.hinthischapter.
(Lefttothereader)
5-10
PlaceobjectsoftheHenclassfromExercise6inaStash.Fetchthemoutandprintthem(ifyouhavenotalreadydoneso,youwillneedtoaddHen:
:
print()).
(Lefttothereader)
5-11
CopytheimplementationandtestfilesforStackinChapter4sothatyoucancompileandtestStack2.hinthischapter.
(Lefttothereader)
5-12
PlaceobjectsoftheHenclassfromExercise6inaStack.Fetchthemoutandprintthem(ifyouhavenotalreadydoneso,youwillneedtoaddHen:
:
print()).
(Lefttothereader)
5-13
ModifyCheshireinHandle.cpp,andverifythatyourprojectmanagerrecompilesandrelinksonlythisfile,butdoesn’trecompileUseHandle.cpp.
(Lefttothereader)
5-14
CreateaStackOfIntclass(astackthatholdsints)usingthe“Cheshirecat”techniquethathidesthelow-leveldatastructureyouusetostoretheelementsinaclasscalledStackImp.ImplementtwoversionsofStackImp:
onethatusesafixed-lengtharrayofint,andonethatusesavector.Haveapresetmaximumsizeforthestacksoyoudon’thavetoworryaboutexpandingthearrayinthefirstversion.NotethattheStackOfInt.hclassdoesn’thavetochangewithStackImp.
Solution:
Here’stheStackOfIntclass:
//:
S05:
StackOfInt.h
#include//forsize_t
#include//forINT_MIN
//VC++doesn’tputsize_tinstd:
#ifndef_MSC_VER
usingstd:
:
size_t;
#endif
structStackImp;//Incompletetypedeclaration
structStackOfInt{
enum{STKERROR=INT_MIN};
voidinit();
voidcleanup();
intpush(int);
intpop();
inttop();
size_tsize();
private:
StackImp*pImpl;//The“smile”
};
///:
~
TodoCheshireCat,IjustdeclaretheStackImpclass(thismakesitan“incomplete”type),anddeclareapointertoitasamemberofStackOfInt.TheimplementationsofStackOfInt’smemberfunctionswillusetheinternalsofStackImpviapImpl,soIhavetodefinethemethodbodiesinaseparate.cppfile(otherwisewe’renothidinganything!
).Here’sthe.cppfileforthearrayversion:
//:
S05:
StackOfInt1.cpp{O}
//Usesanarraytoimplementastack
#include"StackOfInt.h"
//CompletetheincompletetypeStackImp:
//(Thiscouldbeinaseparateheaderfile)
structStackImp{
enum{MAXSIZE=100};
intdata[MAXSIZE];
intptr;
};
voidStackOfInt:
:
init(){
pImpl=newStackImp;
}
intStackOfInt:
:
push(intx){
if(pImpl->ptr==StackImp:
:
MAXSIZE)
returnSTKERROR;
e