cse 332: course review cse 332 course review review session goals –survey and summarize the...
Post on 11-Jan-2016
224 Views
Preview:
TRANSCRIPT
CSE 332: Course Review
CSE 332 Course Review• Review session goals
– Survey and summarize the semester’s material• A chance to clarify/review ideas/examples, ask questions
– Discuss details about the final exam• Comprehensive, weighted a bit towards later material• One page (1 or 2 sided) of notes + pencils/pens allowed
– Will be strictly enforced: if you bring 2 pages, must put 1 away
• All electronics must be off, including cell phones, etc.
• Recommendations for exam preparation– Catch up on any studio exercises you’ve not done– Write up your notes page as you study– Ask questions here and on the message board
CSE 332: Course Review
Lifecycle of a C++ Program
C++ source code
Makefile
Programmer(you)
object code (binary, one per compilation unit) .o
make“make” utility
xterm
console/terminal/window
Runtime/utility libraries
(binary) .lib .a .dll .so
gcc, etc.compiler
linklinker
executableprogram
Eclipse
debugger
precompiler
compiler
link
turnin/checkin
An “IDE”
WebCAT
Visual Studio
window
compile
CSE 332: Course Review
Symbols in Declarations vs. Definitions
• In C++ the = symbol means either initialization or assignment– If it’s used with a type declaration, it means initialization– If it’s used without a type declaration, it means assignment
int j(7); // j is initialized with value 7
int k = 4; // k is initialized with value 4
j = 3; // j is assigned value 3
• In C++ the & symbol also has a similar “dual nature”– If it’s used inside a type declaration, it means a reference (an alias)
• Arguments to function are always declared along with their types
– If it’s used outside a type declaration, it means “address of”
int swap (int & i, int & j); // references to int
int & s = j; // reference s initialized to refer to j
int * p = & j; // pointer p initialized w/ j’s address
CSE 332: Course Review
Review: What’s a Pointer?• A variable holding an address
– Of what it “points to” in memory
• Can be untyped– E.g., void * v; // points to anything
• However, usually they’re typed – Checked by compiler– Can only be assigned addresses of
variables of type to which it can point– E.g., int * p; // only points to int
• Can point to nothing– E.g., p = 0; // points to nothing
• Can change where it points– As long as pointer itself isn’t const – E.g., p = &i; // now points to i
0x7fffdad0
7
int i
int *p
CSE 332: Course Review
Review: What’s a Reference?• Also a variable holding an address
– Of what it “refers to” in memory
• But with a nicer interface– A more direct alias for the object– Hides indirection from programmers
• Must be typed – Checked by compiler– Again can only refer to the type with
which it was declared– E.g., int & r =i; // refers to int i
• Always refers to (same) something– Must initialize to refer to a variable– Can’t change what it aliases
0x7fffdad0
7
int i
int & r
CSE 332: Course Review
Rules for Pointer Arithmetic
int main (int argc, char **argv){ int arr [3] = {0, 1, 2};
int * p = & arr[0]; int * q = p + 1;
return 0;}
• You can subtract (but not add, multiply, etc.) pointers– Gives an integer with the
distance between them
• You can add/subtract an integer to/from a pointer– E.g., p+(q-p)/2 is allowed
but (p+q)/2 gives an error
• Note relationship between array and pointer arithmetic – Given pointer p and integer n, the expressions p[n] and *(p+n) are both allowed and mean the same thing
0xefffdad0
2int arr [3]
int *p
1
0xefffdad0int *q
0
CSE 332: Course Review
How Function Calls Work
• A function call uses the “program call stack”1. Stack frame is “pushed” when the call is made
2. Execution jumps to the function’s code block
3. Function’s code block is executed
4. Execution returns to just after where call was made
5. Stack frame is “popped” (variables in it destroyed)
• This incurs a (small) performance cost– Copying arguments, other info into the stack frame– Stack frame management– Copying function result back out of the stack frame
CSE 332: Course Review
Pass By Value
void foo (){ int i = 7; baz (i);}
void baz (int j){ j = 3;}
7
7 → 3
local variable i (stays 7)
parameter variable j (initialized with the value passed to baz, and then is assigned the value 3)
Think of this as declaration with initialization, along the lines of:int j = what baz was passed;
CSE 332: Course Review
Pass By Reference
void foo (){ int i = 7; baz (i);}
void baz (int & j){ j = 3;}
7 → 3 local variable i
j is initialized to refer to the variable thatwas passed to baz:when j is assigned 3,the passed variableis assigned 3.
7 → 3
again declarationwith initializationint & j = what baz was passed;
argument variable j
CSE 332: Course Review
Rules of Thumb for C++ Exceptions• Use exceptions to handle any cases where the
program cannot behave normally
• Put more specific catch blocks before more general• Don't let a thrown exception propagate out of main
– Instead, always catch any exceptions that propagate up– Then return a non-zero value to indicate program failure
• Do not use or rely on exception specifications– A false promise if you declare them, unless you have fully
checked all the code used to implement that interface– No guarantees that they will work for templates, because a
template parameter could leave them off and then throw
CSE 332: Course Review
Classes, Structs, and Access Permissions• Declaring access control scopes within a class
private: visible only within the class
protected: also visible within derived classes (more later)
public: visible everywhere – Access control in a class is private by default
• but, it’s better style to label access control explicitly
• A struct is the same as a class, except – Access control for a struct is public by default– Usually used for things that are “mostly data”
• E.g., if initialization and deep copy only, may suggest using a struct
– Versus classes, which are expected to have both data and some form of non-trivial behavior
• E.g., if reference counting, etc. probably want to use a class
CSE 332: Course Review
Static Class Members
• Must define static members, usually outside of class– Initialized before any functions in
same compilation unit are called• Static member functions don’t
get implicit this parameter– Can’t see non-static class members– But non-static member functions
can see static members
class Date {
public:
// ...
static void set_default(int,int,int);
private:
int _d, _m, _y;
static Date default_date;
};
Date::Date ()
: _d (default_date._d),
_m (default_date._m),
_y (default_data._y)
{}
Date::operator= (const Date &d){ this->d_ = d.d_; this->m_ = d.m_; this->y_ = d.y_; }
Date Date::default_date(1, 1, 2004);
void Date::set_default(int m, int d, int y)
{
Date::default_date = Date(m, d, y);
}
CSE 332: Course Review
Default and Copy Constructors• Default constructor takes no arguments
– Can supply default values via base/member list– Must do this for const and reference members– Compiler synthesizes one if no constructors are provided
• Does default construction of all class members (a.k.a member-wise)
• Copy constructor takes a reference to a class instance– Compiler provides one by default if you don’t
• Does (shallow) copy construction of all class members
• If you don’t want compiler to generate one of them– Declare private, don’t define, don’t use within class– But, it’s usually best do declare and define both of these
• Default / copy construction of built-in types – Default construction does nothing (leaves uninitialized)– Copy construction fills in the value given
CSE 332: Course Review
Destructors• Constructors initialize objects
– At start of object’s lifetime– implicitly called when object is
created (can also call explicitly)• Often want to make
destructors virtual– More on this when we discuss
inheritance• Destructors clean up afterward
– Compiler provides if you don’t• Does member-wise destruction
– Destructor is implicitly called when an object is destroyed
– Can make destructor private, call it from within a member function
• e.g., a public one called destroy() • Only allows heap allocation
class Calendar { public: Calendar (size_t s); virtual ~Calendar (); // etc ...
private: size_t size_; Date * dates_;};
Calendar::Calendar (size_t s) : size_(s), dates_(0) { if (size_ > 0) { dates_ = new Date[size_]; }}
Calendar::~Calendar () { delete [] dates_;}
CSE 332: Course Review
Assignment Operator (with Copy Trick)• Cleanup/assignment succeed or fail together
class Array {
public:
Array(unsigned int) ;
Array(const Array &); // assume copy constructor makes a deep copy
~Array();
Array & operator=(const Array &a);
private:
int * ints_; // points to a dynamically allocated array of integers
size_t size_; // gives the size of the dynamically allocated array
};
Array & Array::operator=(const Array &a) {
if (&a != this) { // self-assignment test
Array temp(a); // creates new (deep) copy, cleans up old one
std::swap(temp.ints_, ints_);
std::swap(temp.size_, size_);
}
return *this; // allows chaining of assignments in a statement
}
CSE 332: Course Review
Public, Protected, Private Inheritanceclass A {public: int i;protected: int j;private: int k;};
Class B : public A { // ...};Class C : protected A {// ...};Class D : private A {// ...};
• Class A declares 3 variables – i is public to all users of class A– j is protected. It can only be used by methods
in class A or its derived classes (+ friends) – k is private. It can only be used by methods in
class A (+ friends)
• Class B uses public inheritance from A– i remains public to all users of class B– j remains protected. It can be used by methods
in class B or its derived classes
• Class C uses protected inheritance from A– i becomes protected in C, so the only users of
class C that can access i are the methods of class C – j remains protected. It can be used by methods
in class C or its derived classes
• Class D uses private inheritance from A– i and j become private in D, so only methods of
class D can access them.
CSE 332: Course Review
Class and Member Construction Orderclass A {public: A(int i) :m_i(i) { cout << "A“ << endl;} ~A() {cout<<"~A"<<endl;}private: int m_i;};class B : public A {public: B(int i, int j) : A(i), m_j(j) { cout << “B” << endl;} ~B() {cout << “~B” << endl;}private:
int m_j;};int main (int, char *[]) { B b(2,3); return 0;}
• In the main function, the B constructor is called on object b– Passes in integer values 2 and 3
• B constructor calls A constructor– passes value 2 to A constructor via
base/member initialization list• A constructor initializes m_i
– with the passed value 2• Body of A constructor runs
– Outputs “A”• B constructor initializes m_j
– with passed value 3• Body of B constructor runs
– outputs “B”
CSE 332: Course Review
Class and Member Destruction Orderclass A {public: A(int i) :m_i(i) { cout << "A“ << endl;} ~A() {cout<<"~A"<<endl;}private: int m_i;};class B : public A {public: B(int i, int j) :A(i), m_j(j) { cout << “B” << endl;} ~B() {cout << “~B” << endl;}private:
int m_j;};int main (int, char *[]) { B b(2,3); return 0;}
• B destructor called on object b in main• Body of B destructor runs
– outputs “~B”• B destructor calls “destructor” of m_j
– int is a built-in type, so it’s a no-op• B destructor calls A destructor• Body of A destructor runs
– outputs “~A”• A destructor calls “destructor” of m_i
– again a no-op• Compare orders of construction and
destruction of base, members, body– at the level of each class, order of steps
is reversed in constructor vs. destructor– ctor: base class, members, body– dtor: body, members, base class
CSE 332: Course Review
C++ Polymorphism• 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”– Depends on dynamic typing
• Virtual member function/operator, base pointer/reference to derived object
• Template parameters also induce a subtype relation– Known as “interface polymorphism”– Templates impose type requirements (concepts) that types model
• Liskov Substitution Principle (for both kinds of polymorphism)– if S is a subtype of T, then wherever you need a T you can use an S
CSE 332: Course Review
Virtual Functionsclass A {public: void x() {cout<<"A::x";}; virtual void y() {cout<<"A::y";};};
class B : public A {public: void x() {cout<<"B::x";}; virtual void y() {cout<<"B::y";};};
int main () { B b; A *ap = &b; B *bp = &b; b.x (); // prints "B::x" b.y (); // prints "B::y" bp->x (); // prints "B::x" bp->y (); // prints "B::y" ap->x (); // prints "A::x" ap->y (); // prints "B::y" return 0;};
• Only matter with pointer or reference– Calls on object itself resolved statically– E.g., b.y();
• Look first at pointer/reference type– If non-virtual there, resolve statically
• E.g., ap->x();– If virtual there, resolve dynamically
• E.g., ap->y();• Note that virtual keyword need not be
repeated in derived classes– But it’s good style to do so
• Caller can force static resolution of a virtual function via scope operator– E.g., ap->A::y(); prints “A::y”
CSE 332: Course Review
Potential Problem: Class Slicing
• Catch derived exception types by reference
• Also pass derived types by reference
• Otherwise a temporary variable is created – Loses original exception’s “dynamic type”– Results in “the class slicing problem” where only the
base class parts and not derived class parts copy
CSE 332: Course Review
What’s a Design Pattern?
• A design pattern has a name– So when someone says “Adapter” you know what they mean– So you can communicate design ideas as a “vocabulary”
• A design pattern describes the core of a solution to a recurring design problem– So you don’t have to reinvent known design techniques– So you can benefit from others’ (and your) prior experience
• A design pattern is capable of generating many distinct design decisions in different circumstances– So you can apply the pattern repeatedly as appropriate– So you can work through different design problems using it
CSE 332: Course Review
Adapter Structure (Object Form)
• Interface abstract base class provides desired interface
• Impl concrete class provides the implementation• Adapter glues them together via delegation
Interface
Impl
method () = 0;
impl_method ();
Adapter
method () { impl_->impl_method();};
impl_
CSE 332: Course Review
Basic Use of the Singleton Patternclass Portfolio {
public:
static Portfolio * instance();
static void fini();
// . . .
private:
static Portfolio * instance_;
Portfolio ();
virtual ~Portfolio ();
// . . .
};
Portfolio * Portfolio::instance_ = 0;
Portfolio * Portfolio::instance() {
if (instance_ == 0){
instance_ = new Portfolio;
}
return instance_;
}
void Portfolio::fini() {
delete instance_;
instance_ = 0;
}
int main (int, char * []) { try { Stock *s = new Stock ("Alice's Restaurant", 20, 7, 11, 13); Bond *b = new Bond ("City Infrastructure", 10, 2, 3, 5); Portfolio::instance()->add (s); Portfolio::instance()->add (b); Portfolio::instance()->print (); Portfolio::fini(); } catch (Portfolio::error_condition &e) { cout << "Portfolio error: " << e << endl; return -1; } catch (...) { cout << "unknown error" << endl; return -2; } return 0;}
CSE 332: Course Review
What Lives Where in Memory and for How Long • 4 major memory segments
– Global: variables outside stack, heap– Code (a.k.a. text): the compiled program– Heap: dynamically allocated variables– Stack: parameters, automatic and
temporary variables
• Key differences from Java– Destructors of automatic variables called
when stack frame where declared pops– No garbage collection: program must
explicitly free dynamic memory
• Heap and stack use varies dynamically• Code and global use is fixed• Code segment is “read-only”
stack
heap
code
global
CSE 332: Course Review
#include <iostream>
using namespace std;
int main (int, char *[]) {
int * i = new int; // any of these can throw bad_alloc
int * j = new int (3);
int * k = new int[*j];
int * l = new int[*j];
for (int m = 0; m < *j; ++m) {
l[m] = m;
}
delete i;
delete j;
delete [] k;
delete [] l;
return 0;
}
Fill in array values with loop
Array vs. single instance delete
Array vs. single instance new
Dynamic Allocation and De-allocation
CSE 332: Course Review
Scopes of Variables vs. References
• Variables and the pointers and references to them may have different scopes– May result in obvious kinds of lifetime errors we saw earlier– But may also introduce more subtle issues of aliasing– Still can risk destroying an object too soon or too late
• Card a_card; // stack object– Destructor will be implicitly called when a_card is out of scope.
• Card* card_ptr = new Card; // heap object– Requires explicit delete
• Don’t do these– delete &a_card; // delete on a stack object– a_card = *(new Card); // using new to get a temporary variable
CSE 332: Course Review
C++ Memory Management Idioms• Idioms are reusable design techniques in a language
– We’ll look at 4 important ones in C++
• Copy constructor trick for assignment (showed earlier)– Ensures release of existing resource and acquisition of the
new resource both succeed or fail together
• RAII (a.k.a. Guard)– ties dynamic resources to other (esp. automatic) scopes
• Reference counting– ties dynamic lifetime to a group of references
• Copy-on-write– allows more efficient management of multiple aliasing
CSE 332: Course Review
C++11 Smart Pointers
• C++11 deprecates an older smart pointer template– auto_ptr : can guard dynamically allocated memory and pass
ownership around, but doesn’t work with the STL containers and has other limitations
• C++11 provides 3 new smart pointer templates instead– shared_ptr : a general purpose reference counted guard for
dynamic memory (we’ll mostly use this one in this course)– weak_ptr : gives access to a resource that is guarded by a
shared_ptr without increasing reference count (can be used to prevent memory leaks due to circular references)
– unique_ptr : a more complex but potentially very efficient way to transfer ownership of dynamic memory safely (implements C++11 “move semantics”)
CSE 332: Course Review
Operator Overloadingclass A {friend ostream &operator<< (ostream &, const A &);private: int m_a;};
ostream &operator<< (ostream &out, const A &a) { out << "A::m_a = " << a.m_a; return out;}
int main () { A a; cout << a << endl; return 0;}
• Similar to function overloading– Resolved by signature– Best match is used
• But the list of operators and the “arity” of each is fixed– Can’t invent operators– Must use same number of
arguments as for built-in types (except for operator())
– Some operators are off limits:: (scope) . (dot) ?: (conditional)sizeof typeid (RTTI) type casting operators
CSE 332: Course Review
Type Cast Operators (and typedef)int main (int, const char * argv[]) {
// cast away constness char *p = const_cast<char*>(argv[0])
// convert to smaller type int i = 50; char c = static_cast<char>(i);
// downcast a pointer (returns // 0 if *bptr isn’t a Derived) Base * bptr = new Derived; Derived * dptr = dynamic_cast<Derived*>(bptr);
// reinterpret a pointer typedef unsigned long ulong; ulong cookie = reinterpret_cast<ulong>(p);}
• Four type cast operators in C++– Only use these when you must– You cannot overload them– Take a type parameter (generic)
• To get a mutable interface from a const one, use const_cast
• To force a static type conversion that’s known to be safe at runtime use static_cast
• To force a dynamic type conversion that’s known to be safe at runtime use dynamic_cast
• To reinterpret a type as another type (strongest form of casting) use reinterpret_cast
• To alias a type, use typedef
CSE 332: Course Review
Function Templates
template <typename T>void swap(T & lhs, T & rhs) { T temp = lhs; lhs = rhs; rhs = temp;}
int main () { int i = 3; int j = 7; long r = 12; long s = 30; swap (i, j); // i is now 7, j is now 3 swap (r, s); // r is now 30, s is now 12 return 0;}
• The swap function template takes a single type parameter, T– interchanges values of two passed
arguments of the parameterized type
• Compiler instantiates the function template twice in main– with type int for the first call– with type long for the second call– Note that the compiler infers the
type each time swap is called– Based on the types of the arguments
CSE 332: Course Review
Class Templates
template <typename T>
class Array {
public:
Array(const int size);
~Array();
const int size () const;
private:
T * m_values;
const int m_size;
};
int main (int, char**) {
Array <int> a(10);
return 0;
}
• Start with a simple declaration– Which we’ll expand as we go
• Notice that parameterized type T is used within the class template– Type of pointer to array
• When an instance is declared, must also explicitly specify the concrete type parameter– E.g., int in function main (int, char**)
CSE 332: Course Review
Template Specialization: More Polymorphismtypedef char * charptr;
typedef int * intptr;
template <> void print
(ostream & os, const char * message,
const bool & b) {
os << message << std::boolalpha
<< b << endl;
}
template <> void print
(ostream & os, const char * message,
const charptr & s) {
os << message
<< reinterpret_cast<void *> (s);
if (s != 0) {
os << " (points to \""
<< s << "\")"; }
os << endl;
}
template <> void print
(ostream & os, const char * message,
const intptr & ip) {
os << message << ip;
if (ip != 0) {
os << " (points to " << *ip << ")"; }
os << endl;
}
• Specialize on individual typesbool char * int *– Notice the use of typedef
• With specialization, we geti is 7
b is false
ip is 0xfeebf064 (points to 7)
cp is 0x8048c30 (points to "hello, world!")
vp is 0x8048c30
• And, we can reuse the solution!
template <typename T>
void print (ostream & os,
const char * message,
const T & t) {
os << message << t << endl;
}
CSE 332: Course Review
Concepts and Models• Templates impose requirements on type parameters
– Types that are plugged in must meet those requirements– Otherwise, the code won’t compile (and errors will say why)
• The set of requirements imposed is called a concept• Any specific type that meets the requirements is a
model of that concept• What requirement(s) does the expression return first; impose?
• What about while(first != last && *first != value) {
++first;
} const T &
Iterator
CSE 332: Course Review
Interface Polymorphism: Concept Refinement
• A concept C is a refinement of concept D if C imposes all of the requirements of D
• Modeling and refinement satisfy three formal properties– Reflexivity: A concept refines
itself– Containment: if T models C and
C refines D then T models D– Transitivity: If C refines D then
C refines any concept D refines
• What in the OO paradigm is this like? How does it differ?
C1
C2
T1 T2
T3 T4
C0
containment
transitivity
can substitute, e.g., T3 for T1
CSE 332: Course Review
C++ STL Generic Programming Example#include <iostream> #include <iterator> #include <algorithm>
using namespace std; int main (int, const char **) { int numbers [] = {0, 9, 2, 7, 4, 5, 6, 3, 8, 1};
size_t array_dimension = sizeof (numbers) / sizeof (int); // prints out 0 1 2 3 4 5 6 7 8 9 (ascending sort) sort (numbers, numbers + array_dimension); copy (numbers, numbers + array_dimension, ostream_iterator<int>(cout, " ")); cout << endl;
// prints out 9 8 7 6 5 4 3 2 1 0 (descending sort)
sort (numbers, numbers + array_dimension, greater<int>());
copy (numbers, numbers + array_dimension, ostream_iterator<int>(cout, " ")); cout << endl;
// prints out 5 6 2 1 9 4 7 8 3 0 (shuffled) random_shuffle (numbers, numbers + array_dimension); copy (numbers, numbers + array_dimension, ostream_iterator<int>(cout, " ")); cout << endl; return 0; }
native container type (array)
user-defined functor
native iterator type (pointer)
user-defined iterator type
calls
to
ST
L a
lgo
rith
ms
constructor calls
CSE 332: Course Review
Container
Forward Containe
r
Reversible
Container
Random Access
Container
Sequence
Front Insertion Sequenc
e
Back Insertion Sequenc
e
General Container Concepts
refined bymodels
vector
deque
list
• Notice containers can have multiple classifications– Useful to look at differences
between data structures!– Back vs. front insertion– Forward vs. reversible vs.
random access
• More general concepts higher in the hierarchy
• More specific concepts appear farther down
slist
CSE 332: Course Review
Iterator Concept Hierarchy
Input Iterator Output Iterator
Forward Iterator
Bidirectional Iterator
Random Access Iterator
•value persists after read/write•values have locations•can express distance between two iterators
•read or write a value (one-shot)
Linked-list style access (slist)
Bi-linked-list style access
(list)Array/buffer style access
(vector, deque)
“destructive” read at head of stream
(istream)
“transient” write to stream (ostream)
CSE 332: Course Review
Algorithms, Concepts and Models• What very basic concept does the last statement in
STL find, (the line return first;) assume?– Asked another way, what must be able to happen to first
when it’s returned from function find? – Same requirement imposed by by-value iterator parameters
• What other capabilities are required of the Iterator and T type parameters by the STL find algorithm ?
template <typename Iterator, typename T>Iterator find (Iterator first, Iterator last,
const T & value) { while (first != last && *first != value) ++first; return first;}
CSE 332: Course Review
Matching an Algorithm to the Iterators it NeedsCategory/ Operation
Output Input Forward BidirectionalRandom
Access
Read =*p(r-value)
=*p(r-value)
=*p(r-value)
=*p(r-value)
Access -> -> ->->
[]
Write *p=(l-value)
*p=(l-value)
*p=(l-value)
*p=(l-value)
Iteration ++ ++ ++ ++ --++ -- + - += -=
Comparison == != == != == !=== != < > <= >=
What STL iterator category does find require?
CSE 332: Course Review
Algorithm Dispatching via Category Tags• Static dispatching
– Implementations provide different signatures
– Iterator type is evaluated at compile-time
– Links to the best implementation
• Notice how type tags are used
// Based on Austern, pp. 38, 39
template <class Iter, class Distance>
void move (Iter i, Distance d, fwd) {
while (d>0) {--d; ++i;} // O(d)
}
template <class Iter, class Distance>
void move (Iter i, Distance d, rand) {
i += d; // O(1)
}
template <class Iter, class Distance>
void move (Iter i, Distance d) {
move (i, d,
iterator_traits<Iter>::
iterator_category()
)
}
concrete tag (empty struct) type
explicit constructor call
concrete tag (empty struct) type
CSE 332: Course Review
Function Use in an Algorithm#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
using namespace std;
struct Employee {
Employee (const char * n, int i) : name_(n), id_(i) {}
string name_;
int id_;
};
typedef Employee * EmployeePtr;
ostream& operator<< (ostream & os, const EmployeePtr & e) {
os << e->name_ << " " << e->id_ << " ";
return os;
}
// function for comparing EmployeePtrsbool id_compare (const EmployeePtr & e, const EmployeePtr & f) {
return e->id_< f->id_|| (e->id_ == f->id_ && e->name_ < f->name_);
}
int main (int, char *[]) {
vector<EmployeePtr> v;
v.push_back(new Employee("Claire", 23451));
v.push_back(new Employee("Bob", 12345));
v.push_back(new Employee("Alice", 54321));
cout << "v: " ;
copy (v.begin(), v.end(),
ostream_iterator<EmployeePtr>(cout));
cout << endl;
// "v: Claire 23451 Bob 12345 Alice 54321 "
sort (v.begin(), v.end(), id_compare);
cout << "v: " ;
copy (v.begin(), v.end(),
ostream_iterator<EmployeePtr>(cout));
cout << endl;
// "v: Bob 12345 Claire 23451 Alice 54321 "
// clean up: pointers "own" the heap objects
for (vector<EmployeePtr>::iterator i =
v.begin();
i != v.end(); ++i) {
delete *i;
}
return 0;
}
function name ok here
heap object
CSE 332: Course Review
Function Object Use in a Container#include <set>
#include <string>
#include <iterator>
#include <algorithm>
using namespace std;
struct Employee {
Employee (const char * n, int i) : name_(n), id_(i) {}
string name_;
int id_;
};
ostream& operator<< (ostream & os, const Employee & e) {
os << e.name_ << " " << e.id_ << “ ";
return os;
}
// set needs this (orders by name then id)
bool operator< (const Employee & e, const Employee & f) {
return e.name_ < f.name_ || (e.name_ == f.name_ && e.id_ < f.id_);
}
// orders by id then name)struct EmployeeIdComp {
bool operator() (const Employee & e, const Employee & f) {
return e.id_ < f.id_ || (e.id_ == f.id_ && e.name_ < f.name_);
}
};
int main (int, char *[]) {
vector<Employee> v;
v.push_back(Employee("Claire", 23451));
v.push_back(Employee("Bob", 12345));
v.push_back(Employee("Alice", 54321));
cout << "v: " ;
copy (v.begin(), v.end(),
ostream_iterator<Employee>(cout));
// "v: Claire 23451 Bob 12345 Alice 54321 "
set<Employee> s;
s.insert(v.begin(), v.end());
cout << "s: " ;
copy (s.begin(), s.end(),
ostream_iterator<Employee>(cout));
// "s: Alice 54321 Bob 12345 Claire 23451 “
set<Employee, EmployeeIdComp> t;
t.insert(v.begin(), v.end());
cout << "t: " ;
copy (t.begin(), t.end(), ostream_iterator<Employee>(cout));
// "t: Bob 12345 Claire 23451 Alice 54321 “
return 0;
}
function object needed
temporary object
CSE 332: Course Review
STL Functor Concept Hierarchy
Adaptable Function Object
Basic Function Object
Specialized
Predicate
is-refined-byGenerator
UnaryFunction
BinaryFunction
Assignable
AdaptableGenerator
AdaptableUnary
Function
AdaptableBinary
Function
HashFunction
RandomNumber
GeneratorPredicate
AdaptablePredicate
BinaryPredicate
AdaptableBinary
Predicate
StrictWeak
Ordering
CSE 332: Course Review
STL <functional> Before and After C++11• Parts were deprecated in C++11, but are still available in Visual C++ 2010
– E.g., inherit from unary_function and binary_function to decorate a callable object with associated types reflecting its function call signature
– E.g., make a functor for a member function call through a pointer using mem_fun– E.g., make a functor for a member function call through a reference using mem_fun_ref– E.g., bind first argument using binder1st<BinaryFun>– E.g., bind second argument using binder2nd<BinaryFun>– See http://www.sgi.com/tech/stl/table_of_contents.html for more details
• New versions introduced in C++11, are also available in Visual C++ 2010– E.g., bind any argument using bind and _1 _2 _3 etc.– E.g., make a functor for a member function call through pointer or reference using mem_fn– E.g., wrap a callable object with a function call signature using function– New versions provide similar capabilities, but are more consistent and general than before– Availability may depend on compiler version, older code may involve previous versions– See http://en.cppreference.com/w/cpp/utility/functional for more details
CSE 332: Course Review
CSE 332 Course Review• Details about the final exam
– Comprehensive, weighted towards later material– Only one sheet (1 or 2 sided) of notes allowed
• Strictly enforced: if you bring 2 sheets, must put 1 away
– All electronics must be off: iPods/Pads, phones, etc.
• If you have a problem with your exam time– Please contact your Professor for alternatives
• Recommendations for exam preparation– Catch up on any studio exercises you’ve not done– Write up your notes page as you study– Ask questions here and on the message board
top related