• No results found

C++ Crash Kurs. C++ Object-Oriented Programming

N/A
N/A
Protected

Academic year: 2021

Share "C++ Crash Kurs. C++ Object-Oriented Programming"

Copied!
40
0
0

Loading.... (view fulltext now)

Full text

(1)

C++ Crash Kurs

Dr. Dennis Pfisterer

Institut für Telematik, Universität zu Lübeck

http://www.itm.uni-luebeck.de/people/pfisterer

(2)

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; – 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)

(3)

Class

– Defines the structure and behavior – Attributes of a class form the structure – Methods define the behavior

Object or Instance

Notation: Classes and Objects (Instances)

brighter(); darker();

Lamp

int brightness;

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

Analogy

– Car vs. „My BMW“ – Human vs. „me“ l1; ln; … int brightness;
(4)

• Declaration similar to struct‘s

– class Name

{

<access-control>

<data-member>

<method/function>

};

Declaring classes

repeat as often as necessary

<method/function>

};

• Access control for methods and attributes

– public: For anybody

– private: Only within this class

– protected: Within this class and within sub-classes

(5)

class

MyClassName

{

public

:

int method1();

void another_one();

private

:

Declaring classes

Ok. However, it is good practice to have only one private, protected and public block

private

:

void secret_one();

public

:

void another_public_one();

protected

:

void only_visible_to_inherited();

int my_protected_state;

}

;

public block

Don’t forget the ; as this will cause strange compiler

(6)

• 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

C++ class vs. C struct

• Good practice: Always use class in C++

struct x { public: void f(); }; class x { public: void f(); };

1:1

struct x { void f(); //public }; class x { void f(); //private };

(7)

• 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

Using classes

• 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.,

(8)

Using classes

//File: point.h class Point {

public:

set(int x, int y);

#include “point.h” #include <iostream> using namespace std;

int main(int argc, char** argv) set(int x, int y);

move(int dx, int dy); int x(); int y(); private: int x_; int y_; };

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; }

(9)

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

(10)

• Constructor invoked on

object instantiation

• Example

– Point p;

Constructors

//File: point.h

class Point {

public: Point()

{ x_=0; y_=0; } Point(int ax, int ay)

– Point p;

– Point p(1,2);

• Every class should have a

constructor

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_; };

(11)

• Constructors can not be invoked like “normal” methods

– Point p;

p.Point(); Compiler error

• A constructor can be used to create new objects

Constructors

• 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

(12)

• Used instead of value

assignments to members in

constructors

• Provides a more

object-Member initialization lists

Point() { x_=0; y_=0; } Point(int ax, int ay)

{x_ = ax; y_ = ay; } …

• Provides a more

object-oriented 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) {}

(13)

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

(14)

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

Perform possibly necessary cleanup

– Free reserved memory

– Close open files, network connections, etc.

Example

– class Lamp { public: ~Lamp(); };
(15)

• Methods are functions in classes

– <modifier> <type> method-name(<parameter list>);

– Overloading of methods allowed

Implementing methods

• Instances have an identity

– Pre-defined „this“-pointer to itself

– Not available in static members

(16)

Implementing methods: Inline

class Lamp

{

public:

Lamp()

: on_(false), brightness_(10)

.h File

: on_(false), brightness_(10) {} void on() { on_ = true; } private: bool on_; int brightness_; };

(17)

Implementing methods: Separate .cpp File

class Lamp { public: Lamp(); #include “lamp.h“ //---Lamp:: Lamp()

.h File

.cpp File

Lamp(); void on(); private: bool on_; int brightness_; }; Lamp()

: on_(false), brightness_(10) {}

//---void Lamp::on() { on_ = true; }

(18)

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;

– <type> method-name(<parameter list>) const;

• Example

– class Lamp

{

public:

int brightness() const

{ return brightness; }

};

(19)

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

class X

{

public:

static void f(){};

static int i;

};

int X::i = 0;

void X::f() { … }

X::f();

(20)

• Access control is

class-not instance-specific

– Private & protected limit

access of others

– Instances of the same

• class A {

public:

void change(A& other) {

other.i = 10;

C++ class access control

– Instances of the same

class have access to

private members of any

other instance

other.i = 10; } private: int i; }; • A a, b; a.change(b);
(21)

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

• friends have full access to private/protected members

• Example

#include “y.h“ class X { private: void f(); int x;

friend void my_friend();

}; x.h void my_friend() { X x; x.f(); x.x = 19; y.cpp void my_friend(); y.h

(22)

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 • 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 }

(23)

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 • Example – class A { public: A () {} }; class B {

public: explicit B(const A&) {} };

void f(B b) {} int main() {

A a;

(24)

• Demo

(25)

Operator Overloading

Operator Overloading

(26)

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:

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);

(27)

• 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

C++ class: Operator overloading

• Overloadable operators

new + % ~ > /= |= <<= >= -- () delete - ^ ! += %= << == && , [] new[] * & = -= ^= >> != || -> * delete[] / | < *= &= >>= <= ++ ->

(28)

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);
(29)

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-();

(30)

• 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 Vector operator+ (const Vector& a, const Vector& b); };

Operator overloading: Using (friend) functions

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);
(31)

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;

(32)

Operator overloading: Demo

• Demo

(33)

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 – Arithmetic operations (like + and , …) do not change their arguments

– Operator-assignments (like +=) and assignment (=) change the left-hand argument

– Logical operators do not change their arguments – Operations are chainable (e.g., a = b + d * e)

(34)

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

– 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;

(35)

• Operator-assignments (like +=) and assignment (=) change

the left-hand argument

Rule

– Remove const from arguments that are about to be modified

Operator overloading: Parameters & return values/types

• Example (friend function)

– A& operator+=(A

&

left,

const

A

&

right);

• Example (method)

– class A

{

A& operator+=(

const

A

&

right)

;

(36)

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+ (constA&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+=(constA&other) {

i += other.i; return *this; }

(37)

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 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

(38)

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 { – class Vector {

public:

Vector operator++(); //Prefix Vector operator++(int); //Postfix };

Usage (prefix)

– ++x; – x.operator++();

Usage (postfix)

– x++ – x.operator++(0);
(39)

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: private: int i; }; – 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;

(40)

• Recommendation

Operator overloading: Methods or (friend) functions?

Operator Recommended use

All unary operators Member

All unary operators Member

= () [] –> –>* Must be member

+= –= /= *= ^= &= |= %= >>= <<=

Member

References

Related documents