110 likes | 113 Views
This text covers the basics of C++ programming, including interface vs. implementation, information hiding, vectors and strings in C++, common errors with pointers, shallow copy, and returning pointers to temporary locations.
E N D
Chapter 1C++ Basics Review Sections 1.4 and 1.5 and additional material from these slides See examples under Lec3
Interface Vs. Implementation Interface • Interface typically defined in .h files • #included in .cpp file • Preprocessor commands • Guards against multiple inclusion of .h files
Interface Vs. Implementation (contd.) Implementation • Scoping operator • To identify the class corresponding to each function • Remember • Function signatures must match in both interface and implementation • Default parameters are specified only in the interface
Problems without Information Hiding Change in implementation affects the user of a class What will happen if the name ‘OtherData’ is changed to ‘Info’? Debugging is difficult Where will you place breakpoints to figure out when results went wrong? class NHRecord { public: int SocialSecurityNumber; int OtherData; NHRecord(int SSN, int Data); }; #include <iostream> #include "nhrecord.h" using namespace std; int main() { NHRecord nhr(12345678, 1); cout << "InitialInfo " << nhr.OtherData << '\n'; nhr.OtherData = 2; cout << "UpdatedInfo " << nhr.OtherData << '\n'; } #include "nhrecord.h" NHRecord::NHRecord(int SSN, int Data) { SocialSecurityNumber = SSN; OtherData = Data; } 4
Information Hiding and Accessors Get/Set with private data provide access while overcoming the limitations mentioned above The user is not affected if the name ‘OtherData’ is changed to ‘Info’. Breakpoints on the accessors help with debugging class HRecord { int SocialSecurityNumber; int OtherData; public: HRecord(int SSN, int Data); void SetData(int Data); int GetData(); }; void HRecord::SetData(int Data) {OtherData = Data;} int HRecord::GetData() { return OtherData;} int main() { HRecord hr(12345678, 1); cout << "InitialInfo " << hr.GetData() << '\n'; hr.SetData(2); cout << "UpdatedInfo " << hr.GetData() << '\n'; return 0; } 5
vector and string in C++ STL • Replace built-in C++ arrays and strings, respectively • Built-in arrays/string do not act as proper C++ objects • Standard vector class • Gives a size() function • Can be assigned using = • Standard string class • Compared with ==, <, etc. • Can be assigned using = • Gives length() function • Avoid C++ built-in arrays and strings • Instead, use vector and string classes • Exception: code optimized for speed
Common Errors with Pointers Many of these errors may not be detected when you run your program, which make them particularly dangerous int *i; *i = 1; // Wrong. No memory has been assigned to i. i = new int; *i = 1; // OK delete i; if(i != 0) cout << *i << "\n\n"; // Wrong. i is still non-zero, but memory it points to has been deallocated. i = 0; // It is safer to assign 0 after deallocation. cout << *i; // Wrong. Dereferencing the null pointer. if(i != 0) cout << *i; // Not executed i = new int[10]; delete [] i; // Do not use delete i; 7
More Errors with Pointers int i1=1, i2=2; swap(i1, i2); cout << i1 << " " << i2 << "\n\n"; swap(&i1, &i2); cout << i1 << " " << i2 << "\n\n"; i1 = 1; i2 = 2; swapr(i1, i2); cout << i1 << " " << i2 << "\n\n"; void swap(int t1, int t2) { int t = t1; t1 = t2; t2 = t; } void swap(int *t1, int *t2) { int t = *t1; *t1 = *t2; *t2 = t; } void swapr(int &t1, int &t2) { int t = t1; t1 = t2; t2 = t; } 8
Don’t Return Pointers to Temporary Locations i = BadReturn(); // Call to a dangerous function cout << *i << "\n\n"; // Wrong. Dereferencing an invalid pointer. i = OKReturn(); cout << *i << "\n\n"; delete i; i = 0; int *BadReturn() // Dangerous error. { int Answer = 2; return &Answer; } int *OKReturn() { int *Answer; Answer = new int; *Answer = 2; return Answer; } 9
Shallow Copy • Shallow copy can have unexpected consequences with dynamically allocated data class Node { public: char *name; int age; Node(char *n, int a) { name = new char[strlen(n) + 1]; strcpy(name, n); age = a; } ~Node() { cout << "Deleting " << (void *) name << "\n"; delete [] name; } }; Node n1("Gates", 50), *n2 = new Node(n1); cout << n1.name << " " << n1.age << " " << n2->name << " " << n2->age << "\n"; strcpy(n2->name, "Bill"); n2->age = 55; cout << n1.name << " " << n1.age << " " << n2->name << " " << n2->age << "\n"; delete n2; // The destructor frees name, which is common to n1 and to n2 Output Gates 50 Gates 50 Bill 50 Bill 55 Deleting 0x191d0010 Deleting 0x191d0010
Deep Copy Node(const Node &n) { cout << "In copy constructor\n"; name = new char[strlen(n.name)+1]; strcpy(name, n.name); age = n.age; } Node &operator=(const Node &n){ cout << "In assignment\n"; if(this != &n) { if(name) delete [] name; name = new char[strlen(n.name)+1]; strcpy(name, n.name); age = n.age; } return *this; } Node n1("Gates", 50), *n2 = new Node(n1); cout << n1.name << " " << n1.age << " " << n2->name << " " << n2->age << "\n"; strcpy(n2->name, "Bill"); n2->age = 55; cout << n1.name << " " << n1.age << " " << n2->name << " " << n2->age << "\n"; delete n2; // The destructor frees name, which is common to n1 and to n2 Output In copy constructor Gates 50 Gates 50 Gates 50 Bill 55 Deleting 0x4f87050 Deleting 0x4f87010 11