Item 1: Prefer const and inline to #define
I--- why? const advantage?
1. because #define is not part of language prese; eg #define ASPECT_RATIO 3.1345 ,ASPECT_RATIO will be removed by the processor before entered into compiler.
2. about const trick
NOTE: const char * const myName ="shuzjd";
when we need the value of a class constant during compilation of the class. Using enum hack technique.This take advantage of the fact that the value of an enumerated type can be used where ints are expected.
class GamePlayer{
private:
enum {NUM_PLAYER =6};
int scores[NUM_PLSYER];}
II---using inlinde rather than #define
eg: #define max(a,b) ( (a)>(b)? (a):(b))
1. inline int max(int a,int b){ return a>b ? a: b;}
2. eg1. is not quite the same as the macro above,because this version of max can only be called with ints,but a template fixes thet problem quite nicely:
template<class T>
inline const T &max(const T& a,const T& b){ return a>b ? a: b;}
Given the availability of const and inlines, the need for preprocessor is reduced, but it's not completely eliminated.
Because #inclued #ifdef ...#ifndef #endif to play important roles in controlling compilation.
Item2: Prefer<iostearm> to <stdio.h>
type safety and extensibility are cornerstones of the c++ way of life.
Item3:use const whenever possible
a. const modify variables(int or pointer)
char *str="greeeting"; //non-const data; non-const pointer
const char *str="hello"; //const data;non-const pointer;
const char* const str ="shuzjd"; const data;const pointer;
STL iterators are modeled on pointer.
iterator likes a T* pointer;
std::vector<int> ivec;
I...const std::vector<int>::iterator iter = ivec.begin() ; // like T* const;
*ivec=10;
ivec++;//error,iter is const;
2... std::vector<int>::const_iterator cIter=
vec.begin();
*ivec=10;
ivec++;//right, data is const,ivec can change.
b.const modify function
1.const used to return a constant value; it can reduce the client errors.
eg:
class Rational{... };
const Rational operator* (const Rational& lhs,const Rational& rhs);
Q:why result of operator * be a const object?
A: Because if it weren't,clients would be able to make mistake like this:
if( a*b=c)//use const can be able to quickly find the error ,because a*b is const that can't be assignment.
c. const member funcitons
why use that?
It's important to know which funtions modify an object and which may not.
Item 4: Make sure that objects are initialized before they're used.
For non-member objects of built-in types. Need to do this manually.
For example:
1. int x=0; //manual initialization of an int.
2. double d; //"initialization" by reading from
std::cin>>d; //input stream.
The responsibility for initialization falls on constructors. Rule: make sure--all constructors initialize everything in object.
But not to confuse assignment with initialization.
example: Consider a constructor for a class representing entries in an address book
code:
class PhoneNum{...};
class ABEntry{
private:
std::string theName;
std::string theAddress;
std::list<PhoneNum> thePhones;
int numTimesConsulted;
ABEntry(const std::string&name, const std::string& address,const std::list<PhoneNum> phone);
}
ABEntry::ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones) { theName = name; // these are all assignments, theAddress = address; // not initializations thePhones = phones numTimesConsulted = 0; }
A better way to write the ABEntry constructor is to use the member initialization list instead of assignments:
ABEntry::ABEntry(const std::string& name, const std::string& address, const std::list<PhoneNumber>& phones) : theName(name), theAddress(address), // these are now all initializations thePhones(phones), numTimesConsulted(0) {} // the ctor body is now empty
sometimes must be used to initial. For example,data members that are const or are references
the relative order of initialization of non-local static objects defined in different translation units is undefined.
How to elimination the problem that caused by non-local static objects defined in different translation units?
A: Move each non-local static object into its own function.And declared static.These functions return references to the objects they contain. Non-local static objects are replaced with local static objects.
Here's the technique applied to both tfs and tempDir:
class FileSystem { ... }; // as before FileSystem& tfs() // this replaces the tfs object; it could be { // static in the FileSystem class static FileSystem fs; // define and initialize a local static object return fs; // return a reference to it } class Directory { ... }; // as before Directory::Directory( params ) // as before, except references to tfs are { // now to tfs() ... std::size_t disks = tfs().numDisks(); ... } Directory& tempDir() // this replaces the tempDir object; it { // could be static in the Directory class static Directory td; // define/initialize local static object return td; // return reference to it }