previous lecture introduction to oop and c++ data abstraction string example
DESCRIPTION
Reminder: class String (cont.) char* String::getString(){return chars;} void String::setString(char* value){ length = strlen(value); chars = new char[length+1]; strcpy(value, chars); } int String::equals(String *other){ if (length != other->length) return 0; if (strcmp(chars, other->chars) == 0) return 1; return 0; } String.cppTRANSCRIPT
Previous lecturePrevious lecture
• Introduction to OOP and C++• Data Abstraction
– String example
Reminder: Class StringReminder: Class Stringclass String{
char* chars;int length;
public:char* getString();void setString(char* value);int equals(String *other);
{
String.h
int main(){String str; str.setString(“Hi everyone”);printf(“%s\n”, str.getString());if (str.equals(str)==1) printf(“what a coincidence\n”);
}
Reminder: class String (cont.)Reminder: class String (cont.)
char* String::getString(){return chars;}void String::setString(char* value){
length = strlen(value); chars = new char[length+1];strcpy(value, chars);
}int String::equals(String *other){
if (length != other->length)return 0;
if (strcmp(chars, other->chars) == 0)return 1;
return 0;}
String.cpp
2.1 Access control
Public vs. private
Building classes (wrong)Building classes (wrong)class String{
public:char* chars;int length;char* getString();void setString(char* value);int equals(String *other);
{
String.hint main(){
String str1, str2; str1.setString(“Hi everyone”);str2.setString(“Hi everyone”);str2.length = 2;if (str1.equals(str2) ==1)
printf(“equal!\n”); }
Building classes (right)Building classes (right)class String{
char* chars;int length;
public:char* getString();void setString(char* value);int equals(String *other);
{
String.hint main(){
String str1, str2; str1.setString(“Hi everyone”);str2.setString(“Hi everyone”);str2.length = 2; // Compilation error!// Compilation error!if (str1.equals(str2) ==1)
printf(“equal!\n”); }
Why private?Why private?
• Prevent users from causing errors• Localizes future modifications
– Implementation detailsImplementation details are hidden behind a well defined interfaceinterface, which is implementation independent
• The user needs to learn how to use the interface only
• Easier to design and implement
3. Constructors, Destructors, and Overloading
Class String – will it work?Class String – will it work?
char* String::getString(){return chars;}void String::setString(char* value){
length = strlen(value); chars = new char[length+1];strcpy(value, chars);
}int String::equals(String *other){
if (length != other->length)return 0;
if (strcmp(chars, other->chars) == 0)return 1;
return 0;}
String.cpp
class String{char* chars;int length;
public:char* getString();void setString(char* value);int equals(String *other);
{
String.h
IssuesIssues• Nullity checks
– Before using a pointer, ask if it can be null– Always check parameters
1: char* String::getString(){return chars;} 2: void String::setString(char* value){ 3: length = strlen(value); 4: chars = new char[length+1]; 5: strcpy(value, chars); 6: } 7: int String::equals(String *other){ 8: if (length != other->length) 9: return 0;10: if (strcmp(chars, other->chars) == 0)11: return 1;12: return 0;13: }
IssuesIssues• Nullity checks
1: char* String::getString(){return chars;} 2: void String::setString(char* value){
if (value == if (value == NULLNULL) return;) return; 3: length = strlen(value); 4: chars = new char[length+1]; 5: strcpy(value, chars); 6: } 7: int String::equals(String *other){
if if (other == (other == NULLNULL) ) returnreturn 0; 0; 8: if (length != other->length) 9: return 0;
ifif (length == 0) (length == 0) returnreturn 1; 1;//if length != 0, then chars != NULL
10: if (strcmp(chars, other->chars) == 0)11: return 1;12: return 0;13: }
Issues (cont.)Issues (cont.)
• Nullity checks• Memory leaks
1: char* String::getString(){return chars;} 2: void String::setString(char* value){ 3: length = strlen(value); 4: chars = new char[length+1]; 5: strcpy(value, chars); 6: } 7: int String::equals(String *other){ 8: if (length != other->length) 9: return 0;10: if (strcmp(chars, other->chars) == 0)11: return 1;12: return 0;13: }
Issues (cont.)Issues (cont.)
• Nullity checks• Memory leaks
1: char* String::getString(){return chars;} 2: void String::setString(char* value){ 3: length = strlen(value);
ifif (chars != (chars != NULLNULL) ) delete[]delete[] chars; chars; 4: chars = new char[length+1]; 5: strcpy(value, chars); 6: } 7: int String::equals(String *other){ 8: if (length != other->length) 9: return 0;10: if (strcmp(chars, other->chars) == 0)11: return 1;12: return 0;13: }
Any other leaks?
Issues (cont.)Issues (cont.)
• Nullity checks• Memory leaks
int main(){String str; str.setString(“Hi everyone”);printf(“%s\n”, str.getString());if (str.equals(str)==1) printf(“what a coincidence\n”);
}
str variable created, chars=NULL
str.chars allocated
str.chars last used
str variable destroyed
Reminder: Class StringReminder: Class Stringclass String{
char* chars;int length;
public:char* getString();void setString(char* value);int equals(String *other); voidvoid cleanup(); cleanup(); //if (chars != NULL) delete chars;
{ String.h
int main(){String str; str.setString(“Hi everyone”);…str.cleanup();str.cleanup();
}
3.1 Object creation and 3.1 Object creation and destructiondestruction
Variable lifetime – reminder Variable lifetime – reminder
• Memory areas– StackStack
• LocalLocal– Allocated/deallocated when entering/exiting scope
• Global, Static Global, Static – Allocated/deallocated when entering/exiting program
– HeapHeap• DynamicDynamic
– Allocated/deallocated manually
Object creationObject creation
• 2-stage2-stage– Allocate the memoryAllocate the memory
• The memory still contains garbage…– Initialize the objectInitialize the object
• Set the field values• Should be called before the object is used
• Example:Example:String* str = String* str = newnew String(); String();str->init(str->init(“Hello”“Hello”););
Potential for errors!Potential for errors!• Problem:Problem:
– Programmer might forget to initialize – calling init function
• Solution:Solution: – initialization functions called automatically
after allocation– Must have special names to be automatically
recognized– This is the constructor
Constructor: StringConstructor: Stringclass String}
char* chars;int length;
public:String();String();char* getString();void setString(char* value);int equals(String *other);
{String.h
String::String(){chars = NULL;length = 0;
}
String.cpp
Object destructionObject destruction
• Ensure resources used by object are released– Free memory– Close files– Release other (OS, libraries, …) resources
• Need a function called just before an object is destroyed– Invoked automatically– Again, naming convention
Destructor: StringDestructor: Stringclass String}
char* chars;int length;
public:String();~String();char* getString();void setString(char* value);int equals(String *other);
{String.h
String::~String(){if (chars != NULL) delete[] chars;
}
String.cpp
Using the constructorsUsing the constructors
• When is constructor invoked?• When is the destructor invoked?• Wouldn’t it be nice just to write
String str = “Hi everyone”;• But we can do it!
int main(){String str; str.setValue(“Hi everyone”);printf(“%s\n”, str);
}
3.2 Function overloading3.2 Function overloading
Function overloadingFunction overloading• Function overloading:
– Several functions– Same name – Different parameters
• In C: prohibited• In C++: allowed
– Also for constructors– At each call site, compiler finds the target function by
matching the parameters
Constructor overloading: StringConstructor overloading: Stringclass String}
char* chars;int length;
public:String();String(String(charchar* value);* value);~String();char* getString();void setString(char* value);int equals(String *other);
{String.h
String::String(char* value){length = strlen(value); chars = new char[length+1];strcpy(value, chars);
} String.cpp
Using constructors: StringUsing constructors: String
int main(){String str; String str2(“Hi”); String str3 = “Hello”;foo (str3); //foo declared as foo(String)
}
Constructor and destructor:Constructor and destructor:Compiler defaultsCompiler defaults
• If no constructors are declared for a class, compiler will generate default constructor – Takes no parameters
• Absence of default constructor often results in error
• If no destructor is declared for a class, compiler will generate one– Does nothing
Default constructor - exampleDefault constructor - example
class A{ private:
int a; public:
A(int b){a=b;} void print(){…}
};
int main() {
A a1; A a2[10]; a.print();…
}
'A' : no appropriate default constructor available
• Two errors!
Constructor and Destructors: Constructor and Destructors: calling timecalling time
Local variablesThe constructor is called each time the program reaches the variable declarationThe destructor is called each time the program gets out from the scope
Global variablesThe constructorThe constructor is called at the beginning of the programThe destructorThe destructor is called at the end of the program
Dynamic variablesThe constructor is called each time the object allocates with newnewThe destructor is called each time the object deallocate with deletedelete
Static variablesThe constructor is called at the first time the program gets to the variable ideclarationThe destructorThe destructor is called at the end of the program
Calling times - exampleCalling times - example#include “String.h”
String s1(“global string”);
int main() {
String s2(“local string”);
String* s3=new String(“dynamic string”); String* s4=new String(“another dynamic”);
delete s3 ;
return 0;}
#include “String.h”
String s1(“global string”); // s1 c’tor is called
int main() {
String s2(“local string”); // s2 c’tor is called
String* s3=new String(“dynamic string”); // s3 c’tor is called String* s4=new String(“another dynamic”);// s4 c’tor is called
delete s3 ; // s3 destructor is called
return 0; // s2 destructor is called} // s1 destructor is called
// s4 destructor is never called !
Using constructors: StringUsing constructors: String
int main(){String str; String str2(“Hi”); String str3 = “Hello”;foo (str3); //foo declared as foo(String)foo (“Hello”); // will also be ok
}
Parameter matching rulesParameter matching rules
• Exact matching– voidvoid foo(float x) foo(float x) ↔↔ foo(5.0) foo(5.0)
• Matching of built-in types– voidvoid foo(float x) foo(float x) ↔↔ foo(5) foo(5)
• Matching of user-defined types– Types match if a suitable constructor exists– If StringString defines a constructor String(String(charchar* str)* str),,
then voidvoid foo(String x) foo(String x) ↔↔ foo(“Hi”) foo(“Hi”) • foo(“Hi”) foo(“Hi”) →→ {String x(“Hi”); foo(x);} {String x(“Hi”); foo(x);}
3.3 References3.3 References
By-value vs. by-pointerBy-value vs. by-pointer
void swap(int x, int y){int z = x;x = y;y = z;
}
void swap(int *x, int *y){int z = *x;*x = *y;*y = z;
}
Looks worse, but works
void swap(int &x, int &y){int z = x;x = y;y = z;
}
References: looks good and works
What is a reference?What is a reference?
• A convenience– C++ could be defined without it
• A constant pointer…– Initialized at creation – Cannot be changed– Is always valid
• … that is automatically dereferenced
int* x_ptr;int x_val; int& x_ref=x_val;X_ptr = &x_val;
int yval;xptr = &yval; //okxref = &yval; //error
xptr = NULL;xref = ??? //no way to set to NULL
xval += *xptr;xval += xref;
By-value vs. by-pointerBy-value vs. by-pointer
void swap(int x, int y){int z = x;x = y;y = z;
}
void swap(int *x, int *y){int z = *x;*x = *y;*y = z;
}
Looks worse, but works
void swap(int &x, int &y){int z = x;x = y;y = z;
}
References: looks good and works
By-value vs. by-pointer (cont.)By-value vs. by-pointer (cont.)
• By-value parameters:By-value parameters:– Convenient syntax– voidvoid foo(int x): foo(int x):
• foo gets a copy of x• foo changes to the value of x are local to foo
• By-pointer parameters:By-pointer parameters:– voidvoid foo(int *x) foo(int *x) can modify x– Avoids copy (important for large structures)
• voidvoid foo(String *x); foo(“10-K-long-string”); foo(String *x); foo(“10-K-long-string”);– Use const to avoid modification
• voidvoid foo( foo(constconst int *x); int *x);• By-reference parameters:By-reference parameters:
– Like by-pointer in everything except syntax– voidvoid foo(String &x); String( foo(String &x); String(constconst String& other); String& other);
3.4 Copy-constructors3.4 Copy-constructors
Making copies of existing objectMaking copies of existing object
Using constructors: StringUsing constructors: String
int main(){String str; String str2(“Hi”); String str3 = “Hello”;String str4(str2);foo (str3); //foo declared as foo(String)
}
Calls String() Calls String(“Hi”)
Calls String(“Hello”)
Calls copy-constructorString(const String& other)
Copy-constructorsCopy-constructors• Single parameter – reference to the copied object
classclass X{ X{ publicpublic X( X(constconst X& x); X& x);
}}• Called by the compiler
– When an object is initialized using another object of the same class• X x; X x; X x1(x);X x1(x);
– When an object is passed by value• voidvoid foo(X xparam); foo(X xparam);foo(x);foo(x);
• If no copy-constructor defined, compiler adds one– Bitwise copy of the copied object– Not always fits…
Reminder: class StringReminder: class StringClass String{
char* chars;int length;
public:String();String(char* value);String(const String& other);String(const String& other);~String();char* getString();void setString(char* value);int equals(String *other);
{
• Why const?• Why reference?
String copy-constructorString copy-constructor
char* String::getString(){return chars;}String::String(const String& other){
length = other.length; chars = new char[length+1];strcpy(other.chars, chars);
}
String.cpp
Will default copy-constructor work?
String default copy-constructor - String default copy-constructor - exampleexample
int main(){String str1 = “Hello”;String str2(str1);str2.setString(“bye!!”);printf(“%s\n”, str1);…
}
H e l l o \0
6
str1
6
str2
b y e ! ! \0
Rule of thumb: Incase of pointers in the class we need to implement the
• copy-constructorcopy-constructor
• destructordestructor
• assignment operator (next lecture)assignment operator (next lecture)
SummarySummary
• Class string – reminder• Access control• Constructors, destructors• Function overloading• References• Copy constructors