C++ Crash Kurs C++ Object-Oriented Programming Dr. Dennis Pfisterer Institut für Telematik, Universität zu Lübeck http://www.itm.uni-luebeck.de/people/pfisterer
C++ classes A class is user-defined type encapsulating data and operations on that data Example Data of a Point might be int x, y; Operations may be move, draw, Class operations are often called methods or member functions A class offers the ability to be cleanly initialized (using constructors) and destroyed (using destructors) 2
Notation: Classes and Objects (Instances) Class Defines the structure and behavior Attributes of a class form the structure Methods define the behavior Lamp brighter(); darker(); Object or Instance Called the realization of a class Has an identity (this-pointer) Owns a separate set of attributes (state) State changes through method invocation int brightness; l 1 ; Analogy Car vs. My BMW Human vs. me l n ; 3
Declaring classes Declaration similar to struct s class Name <access-control> <data-member> <method/function> repeat as often as necessary Access control for methods and attributes public: For anybody private: Only within this class protected: Within this class and within sub-classes Most data should be private while most functions public 4
Declaring classes class MyClassName public: int method1(); void another_one(); private: void secret_one(); Ok. However, it is good practice to have only one private, protected and public block public: void another_public_one(); protected: void only_visible_to_inherited(); int my_protected_state; Don t forget the ; as this will cause strange compiler errors 5
C++ class vs. C struct Key word class instead of struct Struct and Class are interchangeable struct s now may also have methods struct: public is standard access level class: private is standard access level Good practice: Always use class in C++ struct x void f(); //public struct x public: void f(); 1:1 class x void f(); //private class x public: void f(); 6
Using classes A class can be used just like any other type Instances are defined just like predefined type instances Methods are invoked via variable_name.method_identifier Instances may be assigned, passed as arguments, and returned by functions Example (assignment) Point p1, p2; p1.set( 1, 3); p2 = p1; Automatic element-wise copy (just like with struct) i.e., p2.x = p1.x; p2.y = p1.y; 7
Using classes //File: point.h class Point public: set(int x, int y); move(int dx, int dy); int x(); int y(); private: int x_; int y_; #include point.h #include <iostream> using namespace std; int main(int argc, char** argv) Point p; p.set( 1, 3 ); cout << p( << p.x() <<, << p.y() << ) << endl; } p.move( 10, 10 ); cout << p( << p.x() <<, << p.y() << ) << endl; 8
Initializing classes How to ensure a correct (i.e., predetermined) startup state Constructors Member initialization lists Constructors Member functions called just like the class itself Have no return value Invoked whenever a class instance is allocated Constructor overloading is allowed Member initialization lists Used instead of value assignments to members in constructors Must be used to parameterize constructors of base classes 9
Constructors Constructor invoked on object instantiation Example Point p; Point p(1,2); Every class should have a constructor //File: point.h class Point public: Point() x_=0; y_=0; } Point(int ax, int ay) x_ = ax; y_ = ay; } set(int x, int y); move(int dx, int dy); int x(); int y(); private: int x_; int y_; 10
Constructors Constructors can not be invoked like normal methods Point p; p.point(); Compiler error A constructor can be used to create new objects Point p; p.set(10, 10); p = Point(100, 100); Point() constructs a temporary instance, which is then assigned to p The temporary instance is popped automatically from the stack at the end of the statement 11
Member initialization lists Used instead of value assignments to members in constructors Provides a more objectoriented style Data member are passed arguments to initialize themselves Should be used for (most) members Must be used to parameterize constructors of base classes Point() x_=0; y_=0; } Point(int ax, int ay) x_ = ax; y_ = ay; } Point() : x_(0), y_(0) } Point(int ax, int ay) : x_(ax), y_(ay) } 12
Copy-constructor Used to assign one object to another Signature: Classname(const Classname& other); const is not mandatory, yet often sensible If no copy-constructor is implemented Default copy-constructor generated by the compiler Creates 1:1 (shallow) copy of the other object Problem: Pointers are copied as well, not their pointed-at objects More complex objects should implement a copy constructor 13
Destructors Counterpart to the constructors Invoked immediately before an object is removed from memory Declaration just like a constructor with leading ~ No overloading possible, no parameters, no return value Perform possibly necessary cleanup Free reserved memory Close open files, network connections, etc. Example class Lamp public: ~Lamp(); 14
Implementing methods Methods are functions in classes <modifier> <type> method-name(<parameter list>); Overloading of methods allowed Instances have an identity Pre-defined this -pointer to itself Not available in static members 15
Implementing methods: Inline class Lamp public: Lamp() : on_(false), brightness_(10) } void on() on_ = true; } private: bool on_; int brightness_;.h File 16
Implementing methods: Separate.cpp File class Lamp public:.h File.cpp File Lamp(); void on(); private: bool on_; int brightness_; #include lamp.h //----------------------------------------------------------------------- Lamp:: Lamp() : on_(false), brightness_(10) } //----------------------------------------------------------------------- void Lamp::on() on_ = true; } 17
Implementing methods: const methods Constant methods May not modify attributes nor call non-const methods Only const-methods may be invoked on const instances <type> method-name(<parameter list>) const; Example class Lamp public: int brightness() const return brightness; } 18
Implementing methods: static members Static methods and attributes One instance per class, not per object Can only access other static elements Data elements must be explicitly defined No this pointer available class X public: static void f() static int i; int X::i = 0; void X::f() } X::f(); X::i; 19
C++ class access control Access control is classnot instance-specific Private & protected limit access of others Instances of the same class have access to private members of any other instance class A public: void change(a& other) other.i = 10; } private: int i; A a, b; a.change(b); 20
C++ class access control: friends Selectively disables access control of a class friend method-signature; or friend class class-name; friends have full access to private/protected members Example x.h y.h #include y.h class X private: void f(); int x; friend void my_friend(); void my_friend(); y.cpp void my_friend() X x; x.f(); x.x = 19; } 21
Implicit type conversion using Constructors C++ performs implicit (safe) type conversions E.g., float x = 1; // Conversion from int to float C++ implicit type conversions extended to classes Implicit conversion using constructors or (global) functions Example class A public: A () } class B public: B(const A&) } void f(b b) } int main() A a; f(a); // Wants B, has A } 22
Preventing constructor conversion Automatic conversion sometimes not desired May introduce performance problems (many constructor calls) Implicit conversion are not obvious to others reading the code Use explicit modifier to make implicit conversions explicit only Conversion must be made explicit by invoking the conversion constructor Example class A public: A () } class B public: explicit B(const A&) } void f(b b) } int main() A a; f( B( a ) ); // Explicit conversion from A to B } 23
Demo C++ Stack class 24
Operator Overloading
C++ class: Operator overloading Example class Vector public: Vector(float x = 0.0, float y=0.0) : x_(x), y_(y) } float x() const return x_; } float y() const return y_; } private: float x; float y; Vector add(const Vector& a, const Vector& b) return Vector( a.x() + b.x(), a.y() + b.y() ); } Vector a, b, c; a = add( b, c); Goal: Simpler syntax using a = b + c Assign new semantics to operators for custom data types 26
C++ class: Operator overloading Assign new semantics to operators for custom data types Key word operator Eye-candy, same functionality can be achieved using method calls Variants Method of a class Normal or friend function Overloadable operators new + % ~ > /= = <<= >= -- () delete - ^! += %= << == &&, [] new[] * & = -= ^= >>!= -> * delete[] / < *= &= >>= <= ++ -> 27
Operator overloading: Using methods Definition like normal methods of a class Only the identifier is special OperatorX: X is an operator, e.g. + Example (binary operator+) class Vector Vector operator+(const Vector& other) return Vector( x_ + other.x_, y_ + other.y_); } Usage Vector x, a, b; x = a + b; x = a.operator+(b); 28
Operator overloading: Using methods Example (unary operator-) class Vector } Vector operator-() return Vector( -x_, -y_); Usage Vector a(1,1); a = -a; (-1,-1) a = a.operator-(); 29
Operator overloading: Using (friend) functions Definition like a normal Function Only the identifier is special (operator@, @ is an operator, e.g. +) Example (friend function for binary operator +) class Vector friend friend Vector operator+ (const Vector& a, const Vector& b); Vector operator+ (const Vector& a, const Vector& b) Vector res; res.x = a.x + b.x; res.y = a.y + b.y; return res; } Usage Vector a, b, c; a = b + c; a = operator+ (b, c); 30
Operator overloading: Using (friend) functions Example (friend function for unary operator -) class Vector friend Vector operator- (const Vector& v); Vector operator- (const Vector& v) return Vector(-v.x, -v.y); } Usage Vector a, b; b = -a; b = operator-(a); 31
Operator overloading: Demo Demo C++ Fraction class 32
Operator overloading: Parameters & return values/types Arguments and return values are arbitrary However, there is a useful pattern to follow Typical assumptions Arithmetic operations (like + and, ) do not change their arguments Operator-assignments (like +=) and assignment (=) change the lefthand argument Logical operators do not change their arguments Operations are chainable (e.g., a = b + d * e) 33
Operator overloading: Parameters & return values/types Arithmetic operations (like + and, ) do not change their arguments Logical operators (like <, >=,!=) do not modify the operands Rule Arguments that are not changed are passed as const references Member functions are flagged const Example (friend function) const A operator+(const A& left, const A& right); bool operator>(const A& left, const A& right); Example (method) class A const A operator+(const A& right) const; bool operator>(const A& right) const; } 34
Operator overloading: Parameters & return values/types Operator-assignments (like +=) and assignment (=) change the left-hand argument Rule Remove const from arguments that are about to be modified Example (friend function) A& operator+=(a& left, const A& right); Example (method) class A A& operator+=(const A& right); } 35
Operator overloading: Parameters & return values/types Return value depends on the meaning of the operator If it produces a new value (e.g, +), return a const temporary object so that the result can not be used as an lvalue class A int i; const A operator+ (const A&other) return A( i += other.i ); } } If it modifies the current value, return a (const) reference so that the operator can be chained class A int i; A& operator+=(const A&other) i += other.i; } } return *this; 36
Operator overloading: Return optimization Why NOT use A tmp(1); return a;? Using this prevents the compiler from performing return optimization A tmp(1); return tmp; 1. Temporary tmp object is created including constructor call 2. Copy-constructor copies tmp to return location on the stack 3. Destructor is called for tmp at the end of the scope return A(1); Tells the compiler that this temporary is only intended a return value Object is directly created on the stack Optimized performance using constructor call instead of temporary object 37
Operator overloading: Distinguish post- and prefix Problem: Both ++x and x++ would be operator++ C++ workaround Use a dummy int parameter for the postfix operator No value or semantics, only provides a different method signature Example class Vector public: Vector operator++(); //Prefix Vector operator++(int); //Postfix Usage (prefix) ++x; x.operator++(); Usage (postfix) x++ x.operator++(0); 38
Operator overloading: Methods or (friend) functions? If possible, prefer implementing as a method Always possible if the left operand is the class itself (Friend) functions mandatory when left operand is not the class itself Example class A private: int i; friend ostream& operator<<(ostream& os, const A& a); A a; cout << a= << a << endl; operator<<(cout, a); // Same as above: left operand is of type ostream ostream& operator<<(ostream& os, const A& a) os << a.i; return os; } 39
Operator overloading: Methods or (friend) functions? Recommendation Operator Recommended use All unary operators Member = () [] > >* Must be member += = /= *= ^= &= = %= >>= <<= All other binary operators Member (Friend) function [1] Rob Murray, C++ Strategies & Tactics, Addison-Wesley, 1993, page 47. 40