22
Lecture 8 / 9 Software Engineering Group Philipp D. Schubert C++ Programming

C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Lecture 8 / 9

Software Engineering Group

Philipp D. Schubert

C++ Programming

Page 2: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

1. Object oriented programming

2. Object oriented programming

3. Object oriented programming

4. Object oriented programming

5. Object oriented programming

6. Object oriented programming

7. Object oriented programming

Contents

Page 3: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Polymorphism Dynamic binding (at runtime)

struct shape {

virtual void draw() { cout << "shape" << endl; }

};

struct rectangle : shape {

void draw() override { cout << "rectangle" << endl; }

};

void print_shape(const shape& s)

{

s.draw(); // cannot bind statically

}

int main()

{

shape s;

rectangle r;

print_shape(s);

print_shape(r);

return 0;

}

Static binding (at compile time)

struct shape {

void draw() { cout << "shape" << endl; }

};

void print_shape(const shape& s)

{

s.draw(); // binds statically

}

int main()

{

shape s;

print_shape(s);

return 0;

}

Page 4: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Virtual method table/ vtable

int main()

{

B b;

C c;

call_print(b);

call_print(c);

return 0;

}

User (call_print()) only needs to know location of

pointer to vtbl

Index used for each virtual function

Efficiency compared to normal function call

Time: within 25%, but in reality much smaller

Space: one pointer to vtabl + one vtabl

#include <iostream>

using namespace std;

struct A {

virtual void print() { cout << "A" << endl; }

virtual void other() { cout << "do other stuff" << endl; }

};

struct B : A {};

struct C : A {

void print() override { cout << "C" << endl; }

};

// How can call_print() choose the right print() function?

// size and layout of B and C is UNKOWN to call_print()!!!

void call_print(A& a)

{

a.print();

}

A has virtual functions

Use virtual function table / vtable / vtbl

B

C

A::print()

C::print()

A::other()

A::other()

Page 5: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Virtual method table

class Base

{

public:

FunctionPointer *__vptr;

virtual void function1() {};

virtual void function2() {};

};

class D1: public Base

{

public:

virtual void function1() {};

};

class D2: public Base

{

public:

virtual void function2() {};

};

class Base

{

public:

virtual void function1() {};

virtual void function2() {};

};

class D1: public Base

{

public:

virtual void function1() override {};

};

class D2: public Base

{

public:

virtual void function2() override {};

};

[Figure from http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/]

Page 6: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Special case: Interfaces

Abstract classes/ structs

Miss one or more function implementations

Cannot be instantiated

An interface is an abstract class with no function definitions!

Why is there a need for interfaces?

Example

A bird might quack

But it is not useful to inherit from base class “quack”

Make it an interface!

A duck might inherit from bird

And additionally implements the quack interface

An interface specifies what has to be implemented

Page 7: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Special case: Interfaces

int main()

{

duck d;

d.fly();

d.do_quack();

// the following line does not work

// quack q; cannot instantiate abstract class!

return 0;

}

#include <iostream>

using namespace std;

class bird {

public:

virtual void fly() { cout << "fly" << endl; }

};

class quack {

public:

virtual ~quack() = default;

virtual void do_quack() = 0; //provide no implementation

};

class duck : public bird, public quack {

public:

void quack() override { cout << "quack, quack!" << endl;}

};

Page 8: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Multiple inheritance

Allowing more than one parent

Quite useful

Some language do not support that

Considered as dangerous (Java does not allow this)

“Deadly diamond of death” (diamond problem)

#include <iostream>

using namespace std;

struct A { virtual void print() { cout << "A" << endl; } };

struct B : A { void print() override { cout << "B" << endl; } };

struct C : A { void print() override { cout << "C" << endl; } };

struct D : B, C {};

int main()

{

D d;

d.print();

return 0;

}[Figure from https://upload.wikimedia.org/wikipedia/commons/8/8e/Diamond_inheritance.svg]

What print() should be called?

C++ warns you when this happens

Problem can be mitigated (override print() in D and manually direct the call)

Page 9: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Multiple inheritance

“Deadly diamond of death” (diamond problem)

#include <iostream>

using namespace std;

struct A { virtual void print() { cout << "A" << endl; } };

struct B : A { void print() override { cout << "B" << endl; } };

struct C : A { void print() override { cout << "C" << endl; } };

struct D : B, C {

void print() override { B::print(); }

};

int main()

{

D d;

d.print();

return 0;

}

[Figure from https://upload.wikimedia.org/wikipedia/commons/8/8e/Diamond_inheritance.svg]

What print() should be called?

C++ warns you when this happens

Problem can be mitigated (override print() in D and manually direct the call)

Page 10: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Composition vs Inheritance

Sometimes composition is more useful than inheritance

Depends on your problem

GO does not support inheritance

[Figure from http://pumpkinprogrammer.com/2014/07/14/c-tutorial-inheritance-and-composition/]

Page 11: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Templates vs Inheritance

Inheritance

Is vertical and goes from abstract to more concrete

Example: Shape, triangle, right angle triangle

Runtime abstraction

Dynamic polymorphism

Templates

Is horizontally, defines parallel instances of code

Example: Sorting: integers, doubles, …, can all be sorted

Code generation tool

Static polymorphism

Both are orthogonal: can be used together

Example: I need both to implement a generic static analysis framework

[Figure from http://stackoverflow.com/questions/7264402/when-to-use-template-vs-inheritance/]

Page 12: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Type Casting

Casting is the mechanism of type conversion

Happens implicitly for most primitive types

Be careful with casting

Example: Casting primitive types

int main()

{

int i = (int) 12.1234; // just cut off after decimal point (you might like to use floor and ceil from <cmath>)

short c = (short) 123123123123; // bad: overflow

double d = (double) 14; // okay

double p = 12.5*i; // right computation is casted to the most precise representation involved (double)

cout << p << endl;

cout << i << endl;

cout << c << endl;

cout << d << endl;

return 0;

}

Page 13: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Dynamic cast – reference version

int main()

{

D d; // the most derived object

A& a = d; // upcast, dynamic_cast may be used,

but unnecessary

B& new_c = dynamic_cast<B&>(a); // downcast

C& new_b = dynamic_cast<C&>(a); // sidecast

return 0;

}

#include <iostream>

struct A {

virtual void f() {}; // must be polymorphic

otherwise we cannot dynamic_cast

};

struct B : A {};

struct C : A {};

struct D : B, C {};

Page 14: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Dynamic cast – pointer version

int main()

{

Base* b1 = new Base;

if(Derived* d = dynamic_cast<Derived*>(b1))

{

std::cout << "downcast from b1 to d

successful\n";

}

Base* b2 = new Derived;

if(Derived* d = dynamic_cast<Derived*>(b2))

{

std::cout << "downcast from b2 to d

successful\n";

}

delete b1;

delete b2;

return 0;

}

#include <iostream>

struct Base {

virtual void f() {}; // must be polymorphic

otherwise we cannot dynamic_cast

};

struct Derived: Base {};

Page 15: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Check ISA relation with dynamic cast int main()

{

D d;

try {

A& a = dynamic_cast<A&>(d);

cout << "cast succeeded" << endl;

} catch (const bad_cast& e) {

cout << "cast failed" << endl;

}

D* d_ptr = new D();

A* a_ptr = dynamic_cast<A*>(d_ptr);

if (a_ptr != nullptr) {

cout << "cast succeeded" << endl;

} else {

cout << "cast failed" << endl;

}

delete d_ptr;

return 0;

}

#include <iostream>

#include <typeinfo>

using namespace std;

struct A {

virtual void f() {}; // must be polymorphic

otherwise we cannot dynamic_cast

};

struct B : A {};

struct C : A {};

struct D : B, C {};

Use exceptions to check for references

Check for nullptr for pointers

Page 16: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Const cast#include <iostream>

using namespace std;

void modify(const int& i)

{

const_cast<int&>(i) = 100;

}

int main()

{

int i = 3; // note i is not declared const

const int& cref_i = i;

// cref_i = 5; this line would fail!

const_cast<int&>(cref_i) = 4; // OK: modifies i

cout << "i = " << i << '\n';

int other = 1;

modify(other);

cout << other << endl;

return 0;

}

Cast constness away

Remove constness when underlying type is

not const!

This is bad style

You are working against the type system

Type system shall prevent you from errors

Only use a const cast in rare/ extreme situtations

[Image from http://www.drodd.com/images14/forrest-gump17.jpg]

Page 17: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Reinterpret cast

Converts between type by reinterpreting underlying bit pattern

Returns a different interpretation of bits

#include <iostream>

using namespace std;

int main()

{

int bits = 0b110001010; // is 394 in decimal

double& d = reinterpret_cast<double&>(bits); // is 6.99566e-249

cout << bits << endl;

cout << d << endl;

return 0;

}

Very rarely needed

E.g. if you have to implement some device drivers

I never needed a reinterpet cast

Page 18: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Other casts

Some more casts exist

Static cast

Performing an explicit cast

Casting in hierarchies with non-virtual methods/ or primitive types

int i = 42;

double d = static_cast<double>(i);

Explicit cast

(new type) expression

int i = 2;

double d = (double) i * i;

Implicit conversion

int j = 3;

double e = j;

bool mybool = 1;

Page 19: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

GOTO #include <iostream>

using namespace std;

int main() {

int counter = 0;

label: // loop using goto

cout << counter << '\n';

if (counter < 10) {

counter++;

goto label; // jump

}

for (int x = 0; x < 3; x++) {

for (int y = 0; y < 3; y++) {

cout << "x + y still smaller than 3\n";

if (x + y >= 3)

goto endloop;

}

}

endloop:

cout << '\n';

return 0;

}

An evil mechanism

GOTO just exists

GOTO performs an unconditional jump

When to use GOTO?

If you’d like to introduce bugs

If you’d like to make maintenance impossible

If you’d like to make a program unreadable

Better than encryption

Every program containing GOTO can be

expressed in a program not-containing GOTO

I only saw one example where it was useful

Some router software error handling

[Image from http://zdnet1.cbsistatic.com/hub/i/r/2014/10/04/adf68e5f-4bdc-11e4-b6a0-d4ae52e95e57/resize/770xauto/602ba37ff5be136930d7e9ab78e65bc2/ssl-validation-setup-failure.png]

Page 20: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

GOTO #include <iostream>

using namespace std;

int main() {

int counter = 0;

label: // loop using goto

cout << counter << '\n';

if (counter < 10) {

counter++;

goto label; // jump

}

for (int x = 0; x < 3; x++) {

for (int y = 0; y < 3; y++) {

cout << "x + y still smaller than 3\n";

if (x + y >= 3)

goto endloop;

}

}

endloop:

cout << '\n';

return 0;

}

An evil mechanism

GOTO just exists

GOTO performs an unconditional jump

When to use GOTO?

If you’d like to introduce bugs

If you’d like to make maintenance impossible

If you’d like to make a program unreadable

Better than encryption

Every program containing GOTO can be

expressed in a program not-containing GOTO

I only saw one example where it was useful

Some router software error handling

[Image from http://zdnet1.cbsistatic.com/hub/i/r/2014/10/04/adf68e5f-4bdc-11e4-b6a0-d4ae52e95e57/resize/770xauto/602ba37ff5be136930d7e9ab78e65bc2/ssl-validation-setup-failure.png]

Page 21: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Nice talks about OO

“Intro to the C++ Object Model”, Richard Powell (CppCon 2015)

Technical presentation of OO in C++

https://www.youtube.com/watch?v=iLiDezv_Frk

A more general talk “SOLID Principles of Object Oriented & Agile Desing”, Robert Martin

(Yale school of management 2014)

High level overview

How to design large software systems

https://www.youtube.com/watch?v=TMuno5RZNeE

Page 22: C++ Programming · Special case: Interfaces Abstract classes/ structs Miss one or more function implementations Cannot be instantiated An interface is an abstract class with no function

Questions?

Thank you for your attention