Multi-Paradigm Programming in C++: Exam Review and Guidelines
The review provides important details about the upcoming exam in CSE 428S course, covering topics such as exam time and location, studio submissions, exam format, allowed materials, function templates, and class templates in C++. It explains the expectations, guidelines, and considerations for the exam preparation. Students are reminded about deadlines, guidelines for templates, and materials allowed during the exam to aid in their understanding and preparation.
Download Presentation
Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
E N D
Presentation Transcript
E81 CSE 428S: Multi-Paradigm Programming in C++ Fall 2023 Exam 0 Review Chris Gill cdgill@wustl.edu 1
Exam Time and Location 1-2:20PM Tuesday, October 17 in Green Hall L0120 (not Urbauer 222) CSE 428S Multi-Paradigm Programming in C++ 2
Studios Reminder: Studios 0-11 are due by Monday October 16, at 11:59PM One submission per team in Canvas, please If you have a studio marked Incomplete please address the comment and resubmit! Let me know by email ASAP if you need an extension, and the reason for that request CSE 428S Multi-Paradigm Programming in C++ 3
Exam Format Mostly short answer Some matching of terms Largely intended to test your understanding of concepts and language and library features What does this do? When would you use this? Why is it important? CSE 428S Multi-Paradigm Programming in C++ 4
Materials Allowed Open book, open notes I will bring an extra copy of the textbook What is allowed: Any handwritten or printed notes The course textbook What is not allowed: Electronics: laptops, tablets, phones, etc. Recommendation: write a 1-2 sided notes page! Writing it will help you study Easier to access during exam than printing all notes! CSE 428S Multi-Paradigm Programming in C++ 5
Function Templates A function is a formula from which we can generate type-specific versions of a function [LLM pp.652] That formula also imposes requirements on the specific types with which the template may be parameterized E.g., copy construction for arguments passed by value Those requirements define a set of acceptable types Per Liskov Substitution Principle for interface polymorphism I.e., any type that meets the requirements can be plugged in Design considerations for defining function templates Try to impose as few type requirements as is reasonable E.g., passing by const reference instead of by value avoids requiring copy construction of the types that can be passed in E.g., if you can code efficiently using only operator<don t also require the parameterized types to support operator> CSE 428S Multi-Paradigm Programming in C++ 6
Class Templates Similar considerations for interface polymorphism and design of type requirements as function templates But expanded to all requirements member functions impose E.g., copy constructor requires copy initialization of members and default constructor requires default initialization of them Compiler s ability to deduce parameter types of class templates is often less than for function templates So, may need to add further information to class templates E.g., using typename to tell compiler something is a type E.g., giving forward declarations of class templates like template <typename> class Foo; template <typename> class Baz; Friendship relationships involving class templates Can grant friendship for all instantiations or only specific ones E.g., Baz<T> may say friend class Foo<T>; which means that only instantiations with the same type are friends CSE 428S Multi-Paradigm Programming in C++ 7
Default Template Arguments Useful for defining overridable behavior E.g., providing less<T> as the default comparison operator for a function template that also can use others [LLM pp.670] Illustrates the power of making functions, operators, and other callable objects into templates, as the standard libraries do Collecting related types within templates also may motivate having default types for the template E.g., for a class template that declares and defines operators over numeric types, int may be an appropriate default type Then, as long as the operators still are appropriate for them can plug in other types like float, double, etc. If necessary, can specialize definitions of operators for particular types (a topic we will cover in subsequent lectures) CSE 428S Multi-Paradigm Programming in C++ 8
Iteration Example: Pressure --p; --p; Pressure::lo Pressure::pop ++p; ++p; --p; Pressure::med ++p; ++p; --p; Pressure::hi enum class Pressure {lo, med, hi, pop}; Pressure p = Pressure::lo; operator++(Pressure&); operator--(Pressure&); CSE 428S Multi-Paradigm Programming in C++ 9
How to Debug a Program A debugger helps us observe a program s behavior Step through (and into) functions Watching the call stack and variable values But, before we start using the fancy tools What do we expect the program to do? How might the program fail? Can we make predictions and test them? Thinking: the most powerful way to debug Scientific method should guide what you do hypothesis, prediction, experiment, analysis The tools help you follow this disciplined approach faster 10 CSE 428S Multi-Paradigm Programming in C++
Essential gdb Commands Debug a program from its start bash> gdb studio2 Set a breakpoint at a line or a function entry point (gdb) break parse_and_compute Start execution with command line parameters (gdb) run + + + + + + 1 2 4 8 16 32 64 Print out the value of an expression (gdb) print argv[current_index] Continue execution until the next breakpoint (gdb) continue Show the program s call stack (gdb) where Execute one line, stepping into any functions (gdb) step Execute one line, stepping over any functions (gdb) next 11 CSE 428S Multi-Paradigm Programming in C++
Review: Pass by Value Semantics void foo () { int i = 7; baz (i); } local variable i (stays 7) 7 Think of this as declaration with initialization, along the lines of: int j = what baz was passed; void baz (int j) { j = 3; } parameter variable j (initialized with the value passed to baz, and then is assigned the value 3) 7 3 CSE 428S Multi-Paradigm Programming in C++ 12
Review: Pass by Reference Semantics void foo () { int i = 7; baz (i); } again declaration with initialization int & j = what baz was passed; 7 3 local variable i void baz (int & j) { j = 3; } j is initialized to refer to the variable that was passed to baz: when j is assigned 3, the passed variable is assigned 3. 7 3 argument variable j CSE 428S Multi-Paradigm Programming in C++ 13
Review: Pointers Passed by Value j is initialized with the address (value) that was passed to baz int foo () { int i = 7; return baz (&i); } address-of operator local variable i 7 3 int baz (int * j) { *j = 3; return *j; } dereference operator dereferencing j gives the location to which it points, so the variable whose address was passed is assigned 3. 0x74bead00 argument variable j CSE 428S Multi-Paradigm Programming in C++ 14
Review: Pointers Passed by Reference local variable i local variable j int foo () { int i = 7; int j = 4; int *p = &i; return baz (p, j); } 7 4 0x74bead04 0x74bead00 &i &k parameter q parameter k int baz (int * & q, int & k) { q = &k; return *q; } q references p and k references j: when q is assigned the address of k, the effect is to make p point to j instead of i CSE 428S Multi-Paradigm Programming in C++ 15
Operator Precedence & Associativity The list of operators available in C++ is fixed Each has a symbol that corresponds to that operator Can t add operators that are not already on the list Each operator has a specified associativity Left associative: cout << j << endl; // left shift Right associative: i = j = k = 0; // assignment Relative precedence of operators is also pre-defined Can override precedence/associativity using parentheses LLM chapter 4.12 (Table 4.4) has all the operators with their precedence and associativity (and pages in LLM to read) Operators already defined for built-in types (e.g., int) Implicit type conversions increase their applicability (e.g., <) CSE 428S Multi-Paradigm Programming in C++ 16
C++ Supports Functional Programming There are many callable types we can use or adapt E.g., call object s public function call operator (operator()()) E.g., construct and run a C++ std::thread with it in CSE 532 Function pointers let you store and pass aliases to ordinary C and C++ functions E.g., std::size_t (*p)( const char* ) = std::strlen; Lambda expressions define callable types in-place When combined with templates from the standard <functional> library this gives you generic function objects E.g., function<float(float)> sn = [](auto i) { return std::sin(i); }; CSE 428S Multi-Paradigm Programming in C++ 17
From C++ Functions to C++ Structs/Classes C++ functions encapsulate behavior/transformation Data used/modified by a function is passed in via parameters Can export data a function produces via return statement Classes (and structs) encapsulate state and behavior Member variables maintain each object s state Member functions and operators have direct access to member variables of the object on which they are called Class members are private by default, struct members public by default When to use a struct Use a struct for things that are mostly about the data Add constructors and operators to them to work with library containers/algorithms When to use a class Use a class to encapsulate state behind an interface Prefer classes to support substitution and polymorphism CSE 428S Multi-Paradigm Programming in C++ 18
Access Specifications Declaring access within a class or struct private: visible only within the class protected: also visible within derived classes public: visible everywhere Access control in a class is private by default but, it s better style to specify access explicitly A struct is the same as a class, except that access to members of a struct is public by default CSE 428S Multi-Paradigm Programming in C++ 19
Namespaces Namespaces partition the global namespace [LLM] Avoids collisions between symbols with the same name May risk collisions if you say using namespace in .h files That s also only ok-ish in .cppfiles where it s better to say using std::ostream; and using std::vector; A namespace is a scope [LLM] Header files should use the scoping operator for standard (or other namespace) types, e.g., std::vector etc. The global namespace is indicated by the :: operator with no other symbol in front of it, e.g., ::std::ostream A program s main function is in the global namespace When to introduce a namespace If other scopes (classes etc.) don t distinguish symbols If you want to collect related things in a common scope (which can be done recursively by nesting namespaces) Conveniently, can declare a namespace discontinuously CSE 428S Multi-Paradigm Programming in C++ 20
Nested Classes Nested classes are most often used to define implementation classes [LLM] E.g., the LLM TextQuery::QueryResult nested class I would argue (with LLM) that nested classes are related to the enclosing class, but may somewhat weakly so The nested class is scoped within the enclosing class So, putting their declarations and definitions into the same header and source files (respectively) may be reasonable Declaring a nested class (in a header file) The enclosing class can simply forward declare the nested one, e.g., public: class QueryResult; The nested class declaration then is given like any other class except that its class name is scoped to the enclosing class, as in class TextQuery::QueryResult { } Defining a nested class (in a source file) Nested class definitions are also similarly scoped, as in TextQuery::QueryResult::QueryResult ( ) { } CSE 428S Multi-Paradigm Programming in C++ 21
Overview of C++ Polymorphism Two kinds of types in C++: user-defined vs. built-in User defined types: declared classes, structs, unions including types provided by the C++ standard libraries Other types are built in to C++ itself: int, long, float, A typedef creates a new type name for another (type aliasing) Public inheritance creates sub-types Inheritance only applies to user-defined classes (and structs) A publicly derived class is-a subtype of its base class Known as inheritance polymorphism Template parameters also induce a subtype relation Known as interface polymorphism We ll cover how this works, in depth, later in the semester Liskov Substitution Principle (applies to both) if S is a subtype of T, wherever you need a T you can use an S CSE 428S Multi-Paradigm Programming in C++ 22
C++ Polymorphism, Continued Inheritance polymorphism depends on public virtual member functions in C++ Base class declares a public member function virtual Derived class overrides the base class definition of it Private or protected inheritance encapsulates May not create a substitutable sub-type A privately derived class wraps its base class The class form of the Adapter Pattern does this CSE 428S Multi-Paradigm Programming in C++ 23
Pointers to Data Members When to use pointers to data members To access different members of a class, which have the same type (e.g., strings for last name, first name, student ID, etc.) and then apply that access to different objects (e.g., printing out a tabular roster of all the students in a course) How to use pointers to data members Do not initialize them to point to any data (yet), but rather initialize each one to point to a particular member of a class They then can be dereferenced to fetch a particular member of a particular object (e.g., theobject.*pmember) Note that derived class member pointers can point to members that were inherited from base classes! Public functions returning pointers to data members Lets you smuggle out pointers to private/protected members Provide controlled violations of encapsulation of private or protected member variables without (yet) accessing an object These serve as a deferred form of accessor, when applied CSE 428S Multi-Paradigm Programming in C++ 24
Pointers to Member Functions When to use pointers to member functionss For deferred invocation of member functions (on objects that are selected at run-time) How to use pointers to member functions As with pointers to data members, first declare a pointer to the appropriate member function of a class type Then, combine a dereference of the pointer with the member selection operator on a particular object: (obj.*ptr)() Type aliases for member pointers Used as syntactic sugar to capture complex expressions Tables of pointers to member functions Many C++ compilers use v-tables to implement polymorphism Compiler may generate specific code to resolve some virtual functions at run-time (see LLM pp. 604-605) CSE 428S Multi-Paradigm Programming in C++ 25
Member Functions as Callable Objects We ve looked at how to use the standard function template to wrap a non-member function (in Studio 4) For member functions, take a (const if the function is const or non-const otherwise) reference to a class object in signature Pass an object into a call to it to invoke the member function The mem_fn template does some of the work for us It lets us use auto to generate the appropriate type of callable object based on information the compiler already has The bind template also can be used to generate a callable object from a member function It lets us chain callable objects, member functions, etc. as for plain-old-C functions in the functional programming studio CSE 428S Multi-Paradigm Programming in C++ 26
Dynamic Memory and Smart Pointers Prefer to use safe memory allocation templates E.g., the make_shared function template Does a lot of error checking for you (allocation can fail!) Prefer to use smart pointers to dynamic memory E.g., the shared_ptr class template is often what you want Does reference counting and other useful things for you (ensures safe deallocation along all code paths!) Copy and assignment semantics for shared_ptr Each shared_ptr maintains a reference count, for how many shared_ptr aliases there are to a chunk of dynamic memory Copy construction of a shared_ptr increases reference count Assignment to a shared_ptr decrements reference count for object lhs used to alias, increments it for what both now alias Destruction of a shared_ptr decrements reference count CSE 428S Multi-Paradigm Programming in C++ 27
unique_ptr and weak_ptr The unique_ptr template can be used for direct ownership of a dynamically allocated object Its destructor destroys the object and deallocates the memory Copy construction and copy assignment of unique_ptr are not allowed, but move construction and move assignment are (stay tuned for more about those issues next time) That lets us move unique_ptr aliases up and down call stack The weak_ptr template can be used for aliases that don t participate in shared_ptr reference counting Must lock weak_ptr to make sure what it aliases still exists If so, then it s safe to access the aliased object CSE 428S Multi-Paradigm Programming in C++ 28
Using new and delete Directly Generally not recommended if there s a way to use safe allocation functions and smart pointers instead There is a lot to manage, including handling failures and ensuring deallocation along all possible code paths That said, it s good to know how they work Especially since you may want to dig into library code that uses them, in order to understand how it works Especially since a fair amount of legacy code someone else may have written uses them Use new to initialize (rather than to assign) pointers Prefer to do that where the pointer is declared, if possible Make sure that delete is used safely, exactly once Don t delete an object that code may still try to access Make sure the object is deleted after all possible accesses Make sure the object isn t deleted more than once CSE 428S Multi-Paradigm Programming in C++ 29
Special Forms of Allocation/Deallocation Array versions of new and delete use [] syntax E.g., string * strarray = new string [10]; allocates enough memory, ensures constructor called at each position E.g., delete [] strarray; ensures destructor called at each position, then deallocates the memory Decoupling memory allocation and object initialization Allocators allocate memory (but don t call constructors in it) Then, can repeatedly construct objects in place, either via the allocator s construct method or by using placement new Or, can use algorithms to copy (invokes copy consttuctors) or fill (invokes default constructors) the uninitialized memory Decoupling destruction and deallocation To reverse in-place construction, call destructors explicitly This can be done via the allocator s member function Then, can use the allocator again to deallocate the memory CSE 428S Multi-Paradigm Programming in C++ 30
Copy Contructor/Assignment, Destructor Compiler synthesized copy construction/assignment Does member-wise construction/assignment respectively Can prevent copy construction and/or assignment Declaring either or both of them with = delete E.g., unique_ptr cannot be copy assigned or constructed Generally speaking, any class with a non-empty destructor needs copy construction/assignment and vice versa (so called Rule of Three ) Declaring a copy constructor prevents compiler from synthesizing a default constructor automatically If you need it to do that, you need to ask for that by declaring a default constructor with = default (but not defining it) CSE 428S Multi-Paradigm Programming in C++ 31
Swap functions vs. std::swap Reordering algorithms invoke swap operations E.g., std::sort swaps values in an array to rearrange them If a class declares/defines a type-specific swap function (or member function) that type-specific version is used Otherwise std::swap is used, which uses copy assignment Use of type-specific swap is often preferable E.g., to do a shallow swap or ownership-transferring swap Similarly, class level swap functions should use members type specific swap functions rather than std::swap where possible Use of type-specific swap in assignment operators If type-specific swap operation is provided then assignment can use copy and swap to ensure the old state is destroyed E.g., in the copy assignment operator you can pass in rhs by value and then do just: swap(*this, rhs); return *this; CSE 428S Multi-Paradigm Programming in C++ 32
Semantics of lvalues, rvalues, references Variables, etc. are persistent lvalues that can appear on the left hand side of an assignment operator lvalue references are declared with a single ampersand (&) E.g., int j = 2; int &k = j; // lvalue j, lvalue ref k Expressions are ephemeral rvalues that can appear on the right hand side of an assignment operator rvalue references are declared with two ampersands (&&) E.g., &&r = j * 3; // rvalue ref r CSE 428S Multi-Paradigm Programming in C++ 33
Move Semantics Library function std::move lets us treat lvalue as if it were an rvalue (promises to only assign or destroy it) E.g., int &&r = std::move(j); // not safe to use j now Essentially, the lvalue s implementation has been moved away Move constructor Steals the implementation of the passed rvalue to construct the object on which the constructor is called Move assignment Steals the implementation of the passed rvalue and assigns it to the object on which the assignment operator is called Moved-from object must be destructible That is, it must be able to be destroyed safely even after its implementation has been stolen and given to another object CSE 428S Multi-Paradigm Programming in C++ 34
Materials Allowed Open book, open notes I will bring an extra copy of the textbook What is allowed: Any handwritten or printed notes The course textbook What is not allowed: Electronics: laptops, tablets, phones, etc. Recommendation: write a 1-2 sided notes page! Writing it will help you study Easier to access during exam than printing all notes! CSE 428S Multi-Paradigm Programming in C++ 35
Exam Format Mostly short answer Some matching of terms Largely intended to test your understanding of concepts and language and library features What does this do? When would you use this? Why is it important? CSE 428S Multi-Paradigm Programming in C++ 36
Studios Reminder: Studios 0-11 are due by Monday October 16, at 11:59PM One submission per team in Canvas, please If you have a studio marked Incomplete please address the comment and resubmit! Let me know by email ASAP if you need an extension, and the reason for that request CSE 428S Multi-Paradigm Programming in C++ 37
Exam Time and Location 1-2:20PM Tuesday, October 17 in Green Hall L0120 (not Urbauer 222) CSE 428S Multi-Paradigm Programming in C++ 38
Good Luck! That said, please also remember that Fortune favors the prepared mind. Louis Pasteur Any questions? CSE 428S Multi-Paradigm Programming in C++ 39