250 likes | 397 Views
CMSC 202. Lesson 26 Miscellaneous Topics. Warmup. Decide which of the following are legal statements: int a = 7; const int b = 6; int * const p1 = & a; int * const p2 = & b; const int * p3 = & a; const int * p4 = & b; const int * const p5 = & a; const int * const p6 = & a; p1 = & a;
E N D
CMSC 202 Lesson 26 Miscellaneous Topics
Warmup • Decide which of the following are legal statements: int a = 7; const int b = 6; int * const p1 = & a; int * const p2 = & b; const int * p3 = & a; const int * p4 = & b; const int * const p5 = & a; const int * const p6 = & a; p1 = & a; p3 = & a; p5 = & a;
Today • Overload the dereferencing operator • Weirdness of the * operator! • Bit-wise operators (important for 341) • Binary representation • Binary addition • Bit-masking • ~&, |, ^, << and >>
Disclaimer • The material I am about to present is an advanced concept from 341 • The 341 book (Weiss) actually has it WRONG! • Short write-up with some good code • Linked from the Slides webpage • Topic: • Overloading Pointer Dereferencing • Overloading Conversion Operator • Oooo, Aaaah
Pointer Dereferencing • Problem: • Imagine we want to create a templated Sort • What if we have a collection of pointers? template < class T > void MySort( vector<T> &collection ) { /* code that sorts collection has something like: */ if (collection.at(i) < collection.at(j)) { swap(collection.at(i), collection.at(j)); } } // In main… vector<int*> vec; srand(0); for (int i = 0; i < 1000; ++i) vec.push_back(new int(rand())); • Solution: • We already saw auto_ptr • Roll our own Pointer<T> class What happens when we compare two items of type int* ?
Our Pointer<T> class template <class T> class Pointer { public: Pointer(T *rhs = NULL ) : pointee(rhs) {} bool operator<( const Pointer & rhs ) const { return *pointee < *rhs.pointee; } private: T* pointee; }; What if we want to print the pointee? What if we want to change its value?
Overloading Pointer Dereferencing template <class T> class Pointer { public: Pointer(T *rhs = NULL ) : pointee(rhs) {} bool operator<( const Pointer & rhs ) const { return *pointee < *rhs.pointee; } // Pointer dereferencing operator const T operator * () const { return *pointee; } private: T* pointee; };
Using the Pointer Dereference template <class T> ostream& operator <<(ostream &sout, Pointer<T> p) { sout << *p << endl; return sout; } Dereferencing a class that overloads the pointer dereferencing operator – calls that method! “Smart” pointers
Overloading Conversion Operator template <class T> class Pointer { public: Pointer(T *rhs = NULL ) : pointee(rhs) {} bool operator<( const Pointer & rhs ) const { return *pointee < *rhs.pointee; } // Conversion operator operator const T * () const { return pointee; } private: T* pointee; }; This looks very similar… What’s the difference? Position of the word ‘operator’ Operator name is: const T*
Differences… // Pointer dereferencing operator const T operator * () const { return *pointee; } // Conversion operator operator const T * () const { return pointee; } Dereferencing Returns an object of type T (after dereferencing the data member!) Conversion Converts something of type Pointer into something of type const T* (before dereferencing the data member!)
Final Notes about * • If both dereferencing and conversion are overloaded… • Dereferencing operator takes precidence • (put in some cout statements to verify this!) • Conversion operator • Can be used to convert between ANY two types! Cool! • Good examples in below material • Additional Resources • ANSI/ISO C++ Professional Programmer's Handbook • http://www-f9.ijs.si/~matevz/docs/C++/ansi_cpp_progr_handbook/ch03/ch03.htm#Heading12 • C++ Annotations Version 6.1.2 • http://www.icce.rug.nl/documents/cplusplus/cplusplus09.html#l144 • C/C++ Pointers • http://uvsc.freshsources.com/Operator_Overloading.ppt
Decimal Numbers • Humans • Represent everything in decimal, 1 -> 10 • Base 10 notation • Each position is a power of 10 8 0 3 610 Base 10: count by 10’s 8 * 103 0 * 102 3 * 101 6 * 100 = 800010 + 3010 + 610 = 803610
Binary Numbers • Computers • Represent everything in binary, 1’s and 0’s • Base 2 notation • Each position is a power of 2 1 0 1 12 Base 2: count by 2’s 1 * 23 0 * 22 1 * 21 1 * 20 = 810 + 210 + 110 = 1110
Binary Numbers • Usually represented in sets of 4 digits • 4, 8, 16, 32, etc. • Bit • Binary digit • Byte • Collection 8-bits • Integers stored in 4 bytes or 32 bits • 32-bits • Can represent up to 232-1 values • Two other common programming formats • Octal – base 8 • Has digits 0->7 • Hexadecimal – base 16 • Has digits 0->9 and A->F
Binary Representations • What decimal equivalent are the following binary numbers? • 0001 • 0100 • 1000 • 1001 • 1100 • 1111 • 0101
Binary Addition • Just like decimal addition • Except 12 + 12 == 102 • Carry a 1 when you add two or more 1’s • Let’s try a simple one… In decimal? 1 1 1001 9 + 0011 + 3 1 1 0 0 12 We leave off base subscript if the context is clear…
Binary in C++ • Why do we care? • Binary describes size of data • Integer stored in 32-bits, limited to ~5 billion values (or 232-1) • - ~2.7 billion -> ~2.7 billion • That’s great, but why do we REALLY care? • Assume lots of boolean values… • Can use each bit to represent a separate value! • Compress data, optimize data access • Get at “raw” data • Look for these again in Hash Tables!
Bit-wise Operators • Operate on each bit individually…. • ~ • Bit-wise not • 1 becomes 0 • 0 becomes 1 • & • Bit-wise logical and • 1 if both 1 • 0 otherwise • | • Bit-wise logical or • 1 if either or both 1 • 0 otherwise
More Bit-wise Operators • ^ • Bit-wise exclusive or • 1 if either but not both 1 • 0 otherwise • << N • Bit-wise left shift • Moves all bits to the left N places • Shifts on a zero on the right • Left-most bit(s) discarded • >> N • Bit-wise right shift • Moves all bits to the right N places • Shifts on a zero on the left • Right-most bit(s) discarded
Bit-wise Compound Assignment • &= • & and assign • |= • | and assign • ^= • ^ and assign • <<= • << and assign • >>= • >> and assign
Bit Masking • So, have a bunch of boolean values to store • Often called “flags” • Need two things: • Variable to store value in • Bit-mask to “retrieve” or “set” the value • Use characters – unsigned value char flags = 0; // binary: 0000 char flag4 = 8; // binary: 1000 char flag3 = 4; // binary: 0100 char flag2 = 2; // binary: 0010 char flag1 = 1; // binary: 0001
Bit Masking Operations // Set flag1 to “true” flags = flags | flag1; // 0000 | 0001 // Set flag1 to “false” flags = flags & ~flag1; // 0001 & 1110 // Set several flags to “true” flags = flags | flag1 | flag3; // 0000 | 0001 | 0100 // Set all flags to “false” flags = flags ^ flags; // 0101 ^ 0101 // Set to a specific value flags = 11; // 1011 // Set all flags to “true” flags = flags | ~flags; // 1011 | 0100
Practice • Convert the following decimal digits into binary • 7, 5 • Add them together using binary addition • Check your result using decimal • What about these two numbers? • 9, 13 • Use only 4-bits to represent these numbers • What about negative numbers?
Challenge • Use bit-wise operators to implement binary addition