C++ === Topics ------ * oop * calling conventions * const keyword * implict initialization * explicit initialization * inheritanse - initialization order * void type cast * scope operator (::) * virtual functions * pure virtual functions * impure virtual functions * constructors * virtual destructor * virtual constructors * virtual copy constructor * multiple virtual inheritance * accessing private and protected data members * default constructor, destructor, copy constructor, assignment operator * copy constructor * assignment operator * unaric operator overloading * bitwise operators * bit fields * inline functions * extern "C" * preprocessor * integer constants * evaluation order of the "if" statement * pointers * references * function pointers * memory allocation at a constant address * "volitile" variables * "register" variables * arrays * the heap * the stack * exceptions * RTTI (Run-Time Type Information) * type cast * downcast * upcast * multithreading * scopes * static keyword * namespaces * templates * template functions * template classes * exporting DLLs * DLLs shared memory * I/O * "for" loops with multiple counters * friend Starts Here >> ----------- oop inheritance encapsulation polymorphisms subclass ~ derived class nested class ~ a class in a class calling conventions __stdcall - the standard calling convention for C programs. use it when writing libraries. the function frees it's own stack. __cdecl - the only calling convention that enables variable argument functions (...). the caller frees the stack of the function. fastcall - passes the first 2 parameters in registers. the rest is like __stdcall const keyword const int* p; // pointer to a constant integer int* const p; // constant pointer to an integer const int* const p; // constant pointer to a constant integer void myclass::method() const; // constant method. can't modify the data of the object to which it belongs myclass const obj; // a const object. "this" pointer can be used only whith const member methods method(const pObj); // only methods that are defined as const can recieve constant parameters method(const &obj); implict initialization MyConstructor(int x, int y):myX(x), myY(y) {} - myX and myY are class members. this is the only way to initialize constant data members. * there is no way to determine which one of the objects will be initialized first, since their order of appearance is not taken into a consideration by the compiler. * it is recomended not to path "this" pointer as an implict initializer since there is no way to determine when the initialization process completes and so "this" pointer might be invalid. explicit initialization (via "explicit" keyword) - Disables silent type conversion. If "explicit" is not specified, ctors that take a single non-default argument, can be called via the argument type. e.g. class A { public: explicit A(int num){} }; // Explicit ctor class B { public: B(int num){} }; void main() { A a = 40; // Invalid! Explicit ctor B b = 40; // OK } inheritanse - initialization order Derived::Derived():Base() {} - bottom->up. the base constructor goes first void type cast (C trick - in C++ use templates) - you can pass different data types in a single array of void pointers. it is NOT portable. void** ppv; float* pf = (float*)*ppv; scope operator (::) use to call base class methods from derived class. virtual functions are saved in virutal tables at the begining of the class memory. are mapped at link time. pure virtual functions - can have an implementation for the "core" functionality. impure virtual functions - must be implemented or else linkage will fail. constructors - if you call an overridden virtual function from the base class constructor, it will execute its own copy of the function, NOT the everridden one. virtual destructor - use when implementing polymorphic classes to remove the base class member variables. virtual constructors - not supported in c++. virtual copy constructor virtual AncestorClassName* CurrentClassName::Method() const {} multiple virtual inheritance BaseClass {}; SecondLevelClass_1 : virtual public BaseClass {}; SecondLevelClass_2 : virtual public BaseClass {}; CurrentClass : public SecondLevelClass_1, SecondLevelClass_2 {}; - "virtual" instructs compiler to create one version of BaseClass data members, thus saves space and avoids ambiguities in multiple inheritance class hierarchies. accessing private and protected data members - you can directly access the memory of the class: memset(myObj, 0, sizeof(MyClass)); if you have virtual functions in the class you have to take in-account the offset from the begining of the class memory. default constructor, destructor, copy constructor, assignment operator - those are "canonical methods". it is very recomended to explictly declare them. (if not declared manualy the compiler will declare them anyway). copy constructor ClassName(const ClassName& var) - every member variable has to be recreated for the new object (using the "new" operator). assignment operator - before deleting current members variable make sure that you're not assigning to self. unaric operator overloading - const ClassName& operator++(); - prefix (++i) ClassName operator++(int); - postfix (i++) bitwise operators a ^= b ^= a ^= b - swaps a and b values withought using a temporary. it is NOT portable and thus it's behavior is undefined on other machine than yours. a = a + b; b = a - b; a = a - b; - a portable solution for swaping a and b. the size of the number might exceed the maximum size of the variable (overflow). bit fields - ":" declaration of a 3bit bit field. any values higher than the one specified after the semicollon will not be assigned during the runtime (no warnings are generated). the maximum bits in an integer bit field is 32 e.g. {int bitf:32;} will accept "32" as the highest value. class MyClass{ public: int bitf:3;} MyClass obj; obj.bitf = 0; // or 1 or 2 or 3 are valid inputs inheritanse - "is a" relationship member variables - "has a" relationship inline functions - works only when the function defined where it is declared. (compiler is not obligated to inline the function even if instructed). extern "C" If you define a symbol in a C++ file that will be used by a C program, use extern "C" in the definition. preprocessor # - turnes an identifier into a character array and connects it with the string that fallows: #define EXAMPLE(x) (cout << #x "=" << x << endl) ## - concatinates tokens: #define EXAMPLE(x) (int x##_new_var) integer constants * both lowercase and uppercase are valid int o = 0...; // "0" is an Octal constant - should begin with "0" and then any valid octal number "0..7" int h = 0x...; // "0x" is a Hexadecimal constant - should begin with "0x" and then any valid hex num "0..f" "u" is an Unsigned suffix "l" is a Long suffix "i64" and "ll" are 64bit suffixes "f" is a Float suffix (32bit) "lu"is Long Unsigned, and 0x7FFFL is a Long specified as a Hex constant evaluation order of the "if" statement - in a statement: if (a == 1 && b == 0)... it is guaranteed that if a != 1, the second statement won't be evaluated. pointers - variable that has an address of it's own. it stores addresses returned by the "new" operator. after deleting a pointer set it to NULL: pointer = 0; you can delete any pointer set to NULL. references - it's invalid to pass reference to a NULL object in c++ function pointers - variables, which point to the address of a function int* func(); int* (*fp)(); // C int* (MyClass::*pf)(); // C++ pf = &func; memory allocation at a constant address - be careful not run over an existing memory or you'll trigger an access violation MyClass* p = new ((MyClass*)0x12fe80)MyClass(); "volatile" variables - tells the compiler never to load a variable onto a register. it's important when a variable can be changed outside the program (by the hardware for instance). saving the variable in a register might jeopardise data integrity in this case. volitile int i = 10; "register" variables - instructs the compiler to load the variable into a register whenever possible. it speeds up access to the variable. register int i = 10; arrays - both lines 2 and 3 will result in the same output because array subscripting is commutative in C. it translates to *(3 + a) which is the same as *(a + 3). int a[] = {100, 101, 102, 103, 104}; _tprintf("%d\n", 3[a]); _tprintf("%d\n", a[3]); - string literals are only modifiable when they are used as array initializers char *m = "hello, world!"; m[0] = 'H'; // Invalid! Will crush char n[] = "hello, world!"; n[0] = 'H'; // OK the heap - OS global memory pool. (memory that is allocated by the OS at runtime using the "new" operator). the stack - memory that is allocated for a process/function just before it starts. (the memory is local for that process/function). exceptions - objects that were created "on the heap" are not destroyed. void func1() throw(int, char*); // function that throws int's and char's only void func2() throw(...); // function that can throw any value void func3() throw(); // function that is not allowed to throw anything class myExceprtion {}; void main() { try { // code } catch (myException& ex) { // handle exception here throw; // Pass on the exception object } catch (int iex) { } catch(...) { // catch all block - the last one among multiple catch blocks } } RTTI (Run-Time Type Information) #include class A{}; ... A oA, *pA; typeid(oA).name(); - returns the undecorated class name (readable) typeid(pA).name(); - ... typeid(*pA).name(); - ... typeid(oA).raw_name(); - returns the decorated class name (faster) typeid(pA).raw_name(); - ... typeid(*pA).raw_name(); - ... dynamic_cast(object); - type-safe downcast only applicable to polymorphic classes (at least 1 virtual function at the base class). pointer cast fails - returns 0 pointer. reference cast fails - throws "bad_cast" exception. downcast - casting from a base class to a derived class upcast - casting from a derived class to a base class type cast static_cast(expression) - for compile time user-defined and implicit type conversions. good for non-polymorphic downcasts. it never silently reinterprets bits as a different type. reinterpret_cast(expression) - coerces the expression to be the target type, without conversion. This is inherently unsafe and implementation dependent. const_cast(expression) - removes const and volatile modifiers. The target type must be the same as the type of the expression, except for const or volatile modifiers. multithreading _beginthread, _endthread scopes - variable from a inner scope hides a variable with the same name from the outer scope static keyword - static functions don't pass "this" as the first implict variable (thus used for callback functions). using "static" to limit the scope of an external variable is depricated. use namespaces instead. namespaces directive using namespace [::] [nested-name-specifier] namespace-name - makes everything in the namespace visible in the current scope qualification namespace-name::member-name - the namespace-name required each time when you use member-name declaration using namespace-name::member-name - makes the member-name visible in the current scope withought the need of namespace-name unnamed namespace - same as using static global veriable, which is now forbidden alias namespace very_long_name_space{...} namespace VLN = very_long_name_space; using namespace VLN; - used to avoid name clushes. the using directive takes effect until the end of the scope where it was declared. always public. never inline. * VC note: when porting from vc6 to vc7 you might need explictly specify some system namespaces that vc6 doesn't enforce. templates - the "typename" keyword can be replaced by the "class" keyword. they both mean the same thing, however the "class" keyword might create a confusion since it can be used both for class and function templates. thus it is recomended to use the newer, more generic, "typename" keyword. Note: When using template in a template leave a blank space between the brackets: "vector< pair >" template functions template void MyFunction(ClassT& t, ClassA& a); template classes template class MyClass { public: MyClass(T& new_val); ~MyClass(); private: T my_var; }; template MyClass::MyClass(T& new_val):my_var(new_val){}; exporting DLLs When using __declspec(dllexport) if the calling convention of the function is __stdcall, it will be decorated. To avoid name decoration use __cdecl name convention or use .def files (with __stdcall) instead __declspec(dllexport). DLLs shared memory - a memory that is shared amond all the instances of the dll (all the instances can see it). #pragma data_seg("MySharedMem") HANDLE hCurrentDll = NULL; #pragma data_seg() #pragma comment(linker, "/section:MySharedMem,rws") I/O the old i/o classes are no longer used. use stl I/O streams. "for" loops with multiple counters for (int i=0, int j=1; i<10; ++i, j*=3); friend - by declaring a function, an operator or a class as friend, a class grants those entities to its nonpublic members. \ / / \ \_______________________________________/ /dANIEL - http://thedump.fortunecity.com\ \_______________________________________/ / \ \ / / \