C++ pointers parameter passing modes (value, pointer, reference) arrays, structs/objects how to write a complete class inheritance purposes of inheritance: code reuse and polymorphism static vs. dynamic binding polymorphism polymorphism = subtyping + dynamic binding how is it implemented in C++? (v-tables) when things get called (ctors, dtors, op =, super/sub order) memory management C++ memory model (stack, heap, static) what data is on stack, heap, or static area at this point? heap layout when to use stack vs. heap reference counting smart pointers mark-and-sweep garbage collection 2D arrays on the heap (new [][], spine-with-ribs, manual indexing) multi-file projects header files, implementation files source tree compiling/linking of separate files (phases: preprocess, compile, assemble, link) libraries (static and dynamic) operator overloading templates STL Software Design managing complexity divide-and-conquer abstraction (create abstractions that model application domain) information hiding (hide implementation details) minimize dependencies (between parts of the system) finding/creating abstractions classes are nouns, methods are verbs read the specification use cases characteristics of a well-designed class minimize dependencies (minimize coupling) cohesion layering data structure selection class descriptions runtime interactions between objects Software Implementation Code a little, test a little, code a little, test a little, ... ("big bang" doesn't work) Two main reasons for creating routines 1. top-down decomposition of algorithms 2. avoid code duplication Choose good names for classes, methods, variables, etc. Avoid long parameter lists Properly initialize data Principles of code layout be consistent use whitespace to enhance readability (e.g., blank lines between paragraphs) over-parenthesize expressions avoid deep nesting (how can you remove deep nesting? create more routines) wrap long lines effectively one statement per line Code example: what's wrong with it? Testing/Defensive Programming/Error Handling/Debugging unit testing defensive programming asserts parameter checking Error handling return codes extra status parameter error state exceptions (write a piece of code that throws/catches) basic debugging strategies code reading, tracing, debuggers debugging process: find a reproducible test case that demonstrates bug find point where bug is manifest (crash, bad data, etc.) find smallest possible input that will still reproduce the bug process of elimination to home in on offending code types of memory errors (memory leak, dangling pointer, bounds error) strategies for debugging memory errors (memory tracker, memory watcher, Valgrind-style tools) Tools preprocessor, compiler, linker debuggers make profilers Code Tuning optimizations in Chapters 25 & 26