C++CodingTechniques
AcollectionoftechniquesforwritingC++code
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Outlineforthesession
Buildinglargesystems
Whyonearthdowebother?
ProgrammingGuidelines
Gettingyourcodeorganized
C++CodingIdioms
Provenrecepies
C++Gotcha's
Mistakesalreadymadebyothers
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Goalswhenbuildinglargesystems
Thesystemshouldpromote: Reusability Extensibility Flexibility
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Reusability
Thesystemshouldconsistofcomponentsthatcanbe reused. Reusabilityisnecessaryto:
reducethedevelopmenttime(longterm) improvereliabilityofthesystem
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Extensibility
Extensibilityisnecessaryto: Supportextensionstotheoriginalsystem Supportadditionofnewfeatures
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Flexibility
Thesystemshouldnotberigid
Achangeinonecomponentshouldnotnecessitatechangesinother components
Note:
Dependenciesarenotnecessarilyexplicit Problemsnotcaughtbycompiler Problemsnotcaughtbytesting
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Abstractioniseverything!
Encapsulationhidestheinternalimplementationofa component Interfacesareusedtoprovidemethodsforuserstoworkwith thecomponent Inheritanceisusedtospecializeanabstraction
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Encapsulation
ThemostimportantconceptinOOP
Noencapsuling...noobjectorientation
Hidestheinternalsofacomponent Providesanabstractinterfaceforcomponentusers
Alloperationsarethroughtheinterface
Allowtheimplementationtochange
Norequirementoncomponentuserstochangetheircode
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
Encapsuling:example classWriter{ public: ... voidwrite(inti); voidwrite(floatf); voidwrite(constchar*c_str); ... private: ... };
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 9
Encapsuling:exampleofusage classPoint{ public: voidwrite(Writer*writer)const{ writer>write(x); writer>write(y); } private: intx,y; };
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 10
Encapsulingissues
Encapsulinggoals:
Maintaintheobjectinaconsistentstate Separateimplementationandabstraction Allowimplementationtochange
Definemethodsfortheabstraction Donotdefinemethodsfortheimplementation
Iwilldemonstratesomeexamplesinafewslides
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
11
Encapsulingissues,contd.
Donotexposetheinternalstate
Keepprivatepartstoyourself! Donotexposeinternalseventhroughaccessorfunctions Makeusersrelyonimplementation Mayallowusersto(accidentally)changeinternalstate:
Impossibletomaintainconsistentency Herebedragons!
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
12
Encapsuling:example
classWriter{ Writer represents public: how data is written ... voidwrite(inti); WriteBuf represents voidwrite(floatf); where data is voidwrite(constchar*c_str); written ... private: WriteBufm_buf; };
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
13
Encapsuling:advantagesofthiscode
Interfacecompletelyhidesinternalimplementation
WriteBufandWritercanhascompletelydifferentinterfaces
Implementationcanbechangedfreely
Withoutaffectingtheinterface Hencewithoutchanginganycodethatusestheinterface
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
14
Exposinginternals:examples
Expr::lhs()andExpr::rhs()
Methodnotdefinedfortheabstraction Whatiftheexpressionisunary?
Table::get_cache() and Table::clear_cache()
Cachenotpartoftheabstraction
Notaclearcutcase:dependingondefinition
Objectuserswillrelyonitsexistance Whatifyouwantto(re)moveit?
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
15
Adigressionintomutable
classExpr{ Exprrepresentsan intcompute()const{ expression if([Link]()) [Link](...); Holdacachetoavoidre [Link](); computations } private: ... Cachecache; };
Cacherepresentsavalue cache CacheisinsideExprclass
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
16
Adigressionintomutability
ConsideranExprclasswithacacheinsideandconsiderthe followingcode:
inteval(constExpr&expr){ [Link](); }
$g++[Link] [Link]:Infunction'inteval(constExpr&)': mutable.[Link]rror:nomatchingfunctionforcallto 'Expr::compute()const' mutable.[Link]note:candidatesare:intExpr::compute()<near match>
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
17
Adigressionintomutability
Value eval(constExpr&e) { [Link](); }
Instanceeisconst Cacheinsidetheobject? Fieldsinsideconstobjectsare immutable Codewillnotcompile Usemutable
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
18
Adigressionintomutable
classExpr{ Cacheornocacheisan intcompute()const{ implementationissue if([Link]()) [Link](...); Implementationissues [Link](); shouldnotbevisibleinthe } private: ... mutableCachecache; };
interface Hence:usemutable
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
19
Interfaces:what'sitreallyabout?
Hidingtheinternalsofacomponent Policiesforoperatingonanabstraction Welldesignedintefacespromote:
Reusabilitybyabstractingtheimplementation Flexibilitybyisolatingindependentpartsfromeachother Robustnessbynotallowinguncontrolledchangestotheinternals
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
20
InterfaceDesignGuidelines
Interfacesshouldbedesignedfromtheperspectiveofthe caller
Interfacesarecalledmanytimes,butimplementedjustafew
Documentbeforeimplementation
Writeusescases! Themorethebetter Nodistractionfromimplementationissues
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
21
UsecaseDrivenDesign
Promotescompleteinterfaces
Bywritingusecasesyouputyourselfintheroleoftheinterfaceuser
Spotlimitationsintheinterface Encouragesminimalisticinterfaces
Discouragescreationofmonolithicinterfaces
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
22
Inheritance
Specializationofanclass Implementanabstraction
Aspecialformofspecialization
Strategicextensibility
Possibletoextendthesystemaccordingtothepoliciessetbythe designer Herepoliciesarerepresentedasclasseswithvirtualfunctions
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
23
Inheritance
Writer
writeTo
WriteBuf
FileWriteBuf
StringWriteBuf
SocketWriteBuf
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
24
Inheritance:example
Awritebufferthatdatacanbewrittento Dataiswrittenasablockofbytes Ifthebufferisinabadstate,nodatawillbewritten
classWriteBuf{ public: virtualsize_twrite(void*buf,size_tsz)=0; virtualboolis_good()const=0; };
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
25
Inheritance:example
classFileWriteBuf:publicWriteBuf{ FILE*m_file;//isprivatebydefault public: FileWriteBuf(char*name) :m_file(fopen(name,a+)){} size_twrite(void*buf,size_tsize){ if(m_file) returnfwrite(buf,1,size,m_file); return0; } boolis_good()const{returnm_file!=0;} };
TheWorldsMostPopularOpenSourceDatabase
Copyright2005MySQLAB
26
C++ProgrammingTechniques
AsmrgsbordofvariousC++codingtechniquesand guidelines
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
27
Trustthecompiler
[Link].
Trust...butverify Checkassembleroutputifnecessary
Compilersgoodatstraightforwardcode
Useconstants Avoiddarkcornersofthestandard
Easytounderstandmeanseasytooptimize
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
28
Clevercoding:anexample
ucharfoo_1(ulonga) { return!!(a<<11); }
movl8(%ebp),%eax popl%ebp sall$11,%eax testl%eax,%eax setne%al movzbl%al,%eax ret
Copyright2005MySQLAB
ucharfoo_2(ulonga){ if(a&0x1FFFFF) return1; return0; }
testl$2097151,8(%ebp) popl%ebp setne%al ret
TheWorldsMostPopularOpenSourceDatabase
29
Nogratuitouswritestomemory
Writingtomemorycost
[Link]
Branchescost Writepipelinefriendlycode Recomputevalue?
Writecachefriendlycode Globalvariablescost Localvariablesarecheap
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
30
Gratuitouswritestomemory:example
Functioncomp()doesnot touchmemory Firstversionforcesglobal variabletobewrittento memorybeforecall variableintoautovariable andwritesbackafter computation
intfunc_g(){ g_var+=comp(g_var); g_var+=comp(g_var); g_var+=comp(g_var); returng_var; } Memoryaccesses:10to13 intl_var=g_var; l_var+=comp(l_var); l_var+=comp(l_var); l_var+=comp(l_var); return(g_var=l_var); } Memoryaccesses:5
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 31
Secondversionloadsglobal intfunc_l(){
Includefilehandling
Alwaysuseincludeguards! Nevereverallowanycircularincludes!
Includeguardsdonotprotectagainstcirculardependencies Checkthisonaregularbasis Symptom:weirderrormessagesaboutincompleteorundefined structuresand/orclasses
Organizemoduleas:
Headerfileholdingbasic(nonclass)definitions Headerfileholdingclassdefinitions Codefileholdingimplementations
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
32
Modulestructure
#ifndefFOO_H_INCLUDED #defineFOO_H_INCLUDED #include<cstdlib> classFoo{...}; ... #endif #includefoo.h #include<cstdlib> Foo::Foo(){...} ...
Copyright2005MySQLAB
Headerfile
Includeguard Includewhatisused Forwarddeclareclasses
Sourcefile
Moduleheaderfilefirst Includewhatisused Standardheaderfileslast
TheWorldsMostPopularOpenSourceDatabase 33
RAIIIdiom:Resourceallocationisinitialization
Resourcesareaquiredonconstruction Resourcesarereleasedondestruction
Instanceisdestroyedautomaticallywhenleavingscope Noriskofforgettingtoreleaseresource
Example:
boolpacket(Writer&out,constchar*str,intval) { Writer::Mutexmutex(out); [Link](str); [Link](val); returnout.is_good(); }
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 34
Writingtwoitemsthatshouldbewrittenatomically.
TheLawoftheBigThree
Ifaclassdefinesacopyconstructor,acopyassignment operator,oradestructor,itprobablyneedstodefineall three. Allthreemanipulateownershipoftheresourcesusedbyan object Ifsomeoperationisnotallowed,makethefunctionprivate
Declarationissufficient,nodefinitionnecessary
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
35
Missing:CopyConstructor
classString{ public: String(constchar*c_str) :m_str(newchar[strlen(c_str)]){...} ~String(){delete[]m_str;} private: constchar*m_str; }; Stringmake_string(){ Stringb(Helloworld); returnb; }
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 36
Missing:assignmentoperator
classString{ public: ... String(constString&that) :m_str(newchar[strlen([Link])]){...} private: constchar*m_str; }; Stringmake_string(){ Stringa(Hello); Stringb; b=a; returnb; }
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 37
Assignmentoperator:standardidiom
classString{ public: ... String&operator=(constString&that){ Stringcopy(that); swap(copy); return*this; } voidswap(String&str){ std::swap(m_str,str.m_str); } ... };
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
38
Assignmentoperator:idiomvariations
//Slightlyterserversionofthepreviousone String&String::operator(constString&that){ String(that).swap(*this); return*this; } //Moreoptimizerfriendly String&String::operator=(Stringthat){ swap(that); return*this; }
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
39
[Link]
classMyClass{ private: voidstore(inti){...} public: char * voidstore(doublef){...} }; voidfoo(){ MyClassc; NULL [Link](0); }
error: 'void Cell::store(int)' is private
error: within this context
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
40
Virtualfunctionhandling
Virtualfunctionsshouldbeprivate
Occationallyprotected,butneverpublic
Why?
Separateinterfacefromimplementation Virtualfunctionsarepartofimplementation Implementationdetailsshouldbehidden Hence,virtualfunctionsshouldbeprivate
Note:
Privatefunctionscanbeoverridden
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
41
VirtualFunctionUsage:example
classBase{ public: voidtweak(){ do_tweak(); } private: virtualvoiddo_tweak()=0; }; classDerived:publicBase{ private: virtualvoiddo_tweak(){ std::cout<<HelloWorld!<<std::endl; } };
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 42
Gotcha's
Somepiecesofcodethatdoesnotworkasyouprobably expect
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
43
#1:ConstructorCalling
Callingvirtualfunctionsfrom classA{ constructorsordestructors Objectdoesn'texistuntil afterconstructorcompletes Notanimplementation issue!
Languagedesignissue
public: A(){init();} private: virtualinit(); }; classB:publicA{ ... private: virtualinit(){...} };
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
44
#2:ArraysofObjects
classA{...}; classB:publicA{...intx;}; voidfoo(Aa[]){...a[i]...}; voidbar(){ Bb[20]; foo(b);//?!?!? }
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
45
#3:Initializationor...what?
classString{ public: String(constchar*str){...} }; classConcat:publicExpr{ public: Concat(constString&a, constString&b){...} Stringvalue()const{...} };
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 46
#3:Initializationor...what?
intconcat(char*a,char*b){ Concatstr(String(a),String(b)); [Link](); } error:requestformember 'value'in'str',whichisof nonclasstype'Concat() (String,String)'
Ifsomethinglookslikeadeclaration,itis Paranthesesareallowedaroundparameternames strisdeclaredasfunctionacceptingtwoString(instances) andreturningaConcat(instance)
Copyright2005MySQLAB TheWorldsMostPopularOpenSourceDatabase 47
Recommendedreading
GuruoftheWeekbyHerbSutter [Link] ExceptionalC++StylebyHerbSutter ModernC++ProgrammingbyAndreiAlexandrescu C++Templates:TheCompleteGuidebyDavid [Link]
Notforthefainthearted
Copyright2005MySQLAB
TheWorldsMostPopularOpenSourceDatabase
48