180 likes | 268 Views
Version 1.0. Programming Techniques Course. Version 1.0. Chapter 4 – Copy Constructor, Overloading Operators. String copy-constructor. char* String::getString(){return chars;} String::String(const String& other){ length = other.length; chars = new char[length+1];
E N D
Version 1.0 Programming Techniques Course
Version 1.0 Chapter 4 –Copy Constructor, Overloading Operators
String 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
Copy-constructors • Single parameter – reference to the copied object • class X{ public X(const X& x); } • Called by the compiler • When an object is initialized using another object of the same class • X x; X x1(x); • When an object is passed by value • void foo(X xparam);foo(x); • If no copy-constructor defined, compiler adds one • Bitwise copy of the copied object • Not always fits
Using constructors: String void main(){ String s1(“My String”); String s2(s1); String s3=s1; } What’s the difference? void main(){ String s1(“My String”); String s2(s1); String s3; s3=s1; }
Operators Definition • We want User-defined types to behave the same way as built-in types. • We want operators to be supported, for the uniform convention • The language allows this class String { • char* m_str; • int m_len; • public: • String(); • String(char*); • ~String(); • int operator>(const String& s); • String operator+(const String& s); • char* GetString(); • void SetString(char* newStr); }; • And the usage:
Operators - Usage • Who is the caller? • Who is the parameter? void main() { String s1=“Computer ”; String s2=“Techniques” String s3 = s1+s2; // not operator=, but CCtor } Invokes “function” s1.operator+(s2)
Operators - Implementation int String::operator>(const string& s) { return strcmp(m_str, s.m_str); }
Operators - Implementation String String::operator+(const string& s) { char* old_str = m_str; m_str = new char[m_len+s.m_len+1]; m_len+=s.m_len; strcpy(m_str, old_str); strcat(m_str, s.m_str); delete [] old_str; return this; } Within a member function: explicit name for the object on which the function is called
Operators: Good news • Can be defined and re-defined • Defined by default: & (unary), =, , • Rules: • At least one operand must be class • Cannot define new operators • Cannot change precedence/associativity • Cannot redefine ., ?:, sizeof, ::, .,*
Example: Class Vector class Vector2D{ private: double x, y; public: Vector2D(double x_init=0, double y_init=0): x(x_init), y(y_init){} double getX() const {return x;} double getY() const {return y;} Vector2D add(const Vector2D& other) const {return Vector2D(x+other.x, y+other.y);} } //usage: Vector2D a(3,2), b(1); Vector2D c = a.add(b); cout << “(“ << c.getX() << “,” << c.getY() << ‘)’;
Example: Class Vector class Vector2D{ private: double x, y; public: Vector2D(double x_init=0, double y_init=0): x(x_init), y(y_init){} double getX() const {return x;} double getY() const {return y;} Vector2D operator+(const Vector2D& other) const {return Vector2D(x+other.x, y+other.y);} } //usage: Vector2D a(3,2), b(1); Vector2D c = a+b; cout << “(“ << c.getX() << “,” << c.getY() << ‘)’;
Overloading ++ and -- • Pre- and post-increment • x = 0; cout << x++; cout <<++x; • Pre-increment and pre-decrement – usual unary operators • Vector2D operator++(); • Post-increment and post-decrement – use dummy parameter • Vector2D operator++(int); • Rule of thumb: for performance reasons, use the “pre” versions
Friend access modifier • The following will work: • c=a+b; • c=a+1; • The following will not work: • c=1+b; • The first argument cannot be built-in! • Solution: define the operator not as a member function • But what about encapsulation? • Access modifier friend: allows to access private fields and methods of the class
Example: Class Vector class Vector2D{ private: double x, y; public: Vector2D(double x_init=0, double y_init=0): x(x_init), y(y_init){} double getX() const {return x;} double getY() const {return y;} friend Vector2D operator+( const Vector2D& left, const Vector2D& right); } Vector2D operator+(const Vector2D& left, const Vector2D& right){ return Vector2D(left.x+right.x, left.y+right.y);} //usage: Vector2D a(3,2), b(1); Vector2D c = a+b; cout << “(“ << c.getX() << “,” << c.getY() << ‘)’;
Class Vector: more operators class Vector2D{ … Vector2D operator-() const {return Vector2D(-x, -y);} double operator[](int index) const {return (index == 0)?x:y;} friend ostream& operator<<( ostream& ostr, const Vector2D& v); } ostream& operator<<(ostream& ostr, const Vector2D& v){ return ostr << “(“ << v.x << “,” << v.y << ‘)’; } //usage: Vector2D a(3,2), b(1); Vector2D c = -a; cout << “(“ << c[0] << “,” << c[1] << ‘)’; cout << c << b << a;
operator= • By default: bitwise copy • Will this work for Vector2D? • Will this work for String? • Rule of thumb: either you need all of {destructor, copy-constructor, operator=} or you need none • Rules: • MyClass& MyClass::operator=(const MyClass& other) • Return *this • Define as member to ensure target object is assignable
operator= : example class String{ … public: String& operator=(const String& other){ if (this == &other) return *this; if (m_str != NULL) delete[] m_str; m_len = other.m_len; m_str = new char[m_len+1]; strcpy(m_str, other.m_str); return *this; }