Notes on C++ References ~ http://www.bogotobogo.com/cplusplus/functors.php http://en.wikipedia.org/wiki/C%2B%2B11 Contents ~ History ~ Constructors ~ Overloading ~ Effective C++ By Scott Meyers ~ Function Objects - Functors ~ Type Inspection ~ ======================================================================== History ~ C++98, C++03 (i.e. 2003), C++11 ======================================================================== Constructors ~ Copy Constructor Vs Operator = overloading: The copy constructor performs first-time initialization of objects that used to be raw memory. The assignment operator, OTOH, overrides existing values with new ones. More often than never, this involves dismissing old resources (for example, memory) and allocating new ones. Note: Beware of self assignment: a = a ; Function calling by value, uses copy constructor, not operator = !!! The default assignment uses, default destructor followed by default copy constructor ?? You may implement assignment operator using copy constructor, not other way: Default = operator is bitwise copy only. No destructor is called. Default Copy constructor is to call default constructor func if exists, otherwise just allocates memory with junk contents. To prevent accidental use of default constructor, make constructor private. Many times we are required to define both a copy constructor and an assignment operator : if we need one we are likely to need the other. * Copy constructor with one arg also defines default type conversion: A(int) => A a=10; will work! Class& operator=(MyClass& other) { swap(other); // Byte wise swapping !!! return *this; } ======================================================================== Overloading ~ // Overloaded int cast operator int() { return m_nCents; } /* Type casting */ float operator()(float f) { ... } /* Functor- Class acts like func*/ operator++(int) /* post increment */ operator++() /* pre increment */ operator void*() const /* casting to (void*) */ operator!() const operator*() Other operators: =, + - / * (binary) * (unary is deref), += -= /= *= | & ^ ~ |= ... Overload Class as boolean: This allows expressions like: while (cin) { ... } when cin encounters EOF, the bool typecast returns false! operator bool() const ======================================================================== Effective C++ By Scott Meyers ~ Idioms: Item 10: Write operator delete if you write operator new. Constructors, Destructors, and Assignment Operators Item 11: Declare a copy constructor and an assignment operator for classes with dynamically allocated memory. Item 12: Prefer initialization to assignment in constructors. Item 14: Make sure base classes have virtual destructors. Item 15: Have operator= return a reference to *this. Item 16: Assign to all data members in operator=. (if you override) Item 17: Check for assignment to self in operator=. Item 19: Differentiate among member functions, non-member functions, and friend functions. Example: operator * for Class: member or global ? obj_a * 2 AND 2 * obj_a ; Start with member functions, but add global function too. Item 20: Avoid data members in the public interface. Item 21: Use const whenever possible. Item 22: Prefer pass-by-reference to pass-by-value. (but not always! Item23) Item 24: Choose carefully between function overloading and parameter defaulting. Item 25: Avoid overloading on a pointer and a numerical type. (Because NULL is 0) Item 26: Guard against potential ambiguity. Example: Choose typecast operator () or constructor when implicit conversion from A to B should happen ? Item 27: Explicitly disallow use of implicitly generated member functions you don't want. Example: private: Array& operator=(const Array& rhs); This will disallow arr1 = arr2; operation !!! Item 28: Partition the global namespace. namespace mymodule { const int LIB_VERSION = 3; } Item 29: Avoid returning "handles" to internal data. Example: char *ptr used by String. Item 32: Postpone variable definitions as long as possible. e.g. for(int i=0; ... ); Item 34: Minimize compilation dependencies between files. To hide implementation details, typically you declare the pointer to class of the implementation, so that you have a concrete class but the implementation can be delayed later! Example: class Person { public: Person(const string& name, const Address& addr); virtual ~Person(); private: PersonImpl *impl; // pointer to implementation }; Item 36: Differentiate between inheritance of interface and inheritance of implementation. Item 36: Differentiate between inheritance of interface and inheritance of implementation. i.e. how pure virt functions are helpful to clarify that there is no default implementation. To avoid accidental inheritance of implementation *and* to make default implementation available do: class Airplane { public: virtual void fly(const Airport& destination) = 0; ... protected: void defaultFly(const Airport& destination); }; Item 37: Never redefine an inherited nonvirtual function. i.e. Always define virtual functions if you ever foresee that it may be overridden. Item 38: Never redefine an inherited default parameter value. virtual functions are dynamically bound, but default parameter values are statically bound. Item 39: Avoid casts down the inheritance hierarchy. unless you *really* know what you are doing. Item 40: Model "has-a" or "is-implemented-in-terms-of" through layering. i.e. composition. Item 41: Differentiate between inheritance and templates. Item 42: Use private inheritance judiciously. It is not "is-a" relationship. but then what ? Note: compilers will generally not convert a derived class object into a base class object. You just inherit the implementation. Nothing to do with design. Item 43: Use multiple inheritance judiciously. Diamond Problem: A => B|C ; B and C overrides A's method differently Now (B,C)=>D; What method does D inherit ? pls->Lottery::draw(); <== To resolve name ambiguity in parent. Item 44: Say what you mean; understand what you're saying. In declaring a nonvirtual member function, what you're really saying is that the function represents an invariant over specialization, and it would be disastrous if you didn't know that. A common base class means common traits. Public inheritance means isa. Private inheritance means is-implemented-in-terms-of. Layering means has-a or is-implemented-in-terms-of. A pure virtual function means that only the function's interface is inherited. A simple virtual function means that the function's interface plus a default implementation is inherited. A nonvirtual function means that the function's interface plus a mandatory implementation is inherited. - Private virtual function does not make sense. Some tips from Effective Java: Chapter 4. Classes and Interfaces Item 12: Minimize the accessibility of classes and members Item 13: Favor immutability Item 14: Favor composition over inheritance Item 15: Design and document for inheritance or else prohibit it. Item 16: Prefer interfaces to abstract classes Item 17: Use interfaces only to define types Item 18: Favor static member classes over nonstatic Chapter 5. Substitutes for C Constructs Item 19: Replace structures with classes Item 20: Replace unions with class hierarchies Item 21: Replace enum constructs with classes Item 22: Replace function pointers with classes and interfaces Chapter 6. Methods. Item 23: Check parameters for validity. Item 24: Make defensive copies when needed. Item 25: Design method signatures carefully. Item 26: Use overloading judiciously Item 27: Return zero-length arrays, not nulls. Item 28: Write doc comments for all exposed API elements. Chapter 7. General Programming.. Item 29: Minimize the scope of local variables Item 30: Know and use the libraries. Item 31: Avoid float and double if exact answers are required. Item 32: Avoid strings where other types are more appropriate Item 33: Beware the performance of string concatenation Item 34: Refer to objects by their interfaces ======================================================================== Function Objects - Functors ~ Idea is that the functions can be returned as objects. i.e. Objects can act like functions. Somewhat like Python and scripting languages where Functions are first class objects. include struct absValue { float operator()(float f) { return f > 0 ? f : -f; } }; int main( ) { using namespace std; float f = -123.45; absValue aObj; float abs_f = aObj(f); cout << "f = " << f << " abs_f = " << abs_f << endl; return 0; } ======================================================================== C++11 http://en.wikipedia.org/wiki/C%2B%2B11 ======================================================================== Type Inspection ~ C++11 allows: auto other_variable = 5; The type of other_variable is int. Additionally, the keyword decltype can be used to determine the type of an expression at compile-time: int some_int; decltype(some_int) other_integer_variable = 5; auto is also useful for reducing the verbosity of the code: for (std::vector::const_iterator itr = myvec.cbegin(); itr != myvec.cend(); ++itr) for (auto itr = myvec.cbegin(); itr != myvec.cend(); ++itr) The type denoted by decltype can be different from the type deduced by auto. #include int main() { const std::vector v(1); auto a = v[0]; // a has type int decltype(v[0]) b = 1; // b has type const int&, the return type of // std::vector::operator[](size_type) const auto c = 0; // c has type int auto d = c; // d has type int decltype(c) e; // e has type int, the type of the entity named by c decltype((c)) f = c; // f has type int&, because (c) is an lvalue decltype(0) g; // g has type int, because 0 is an rvalue } ========================================================================