• No results found

Programsystemkonstruktion med C++

N/A
N/A
Protected

Academic year: 2021

Share "Programsystemkonstruktion med C++"

Copied!
29
0
0

Loading.... (view fulltext now)

Full text

(1)

Daniel Aarno

bishop@kth.se

Programsystemkonstruktion med C++

Övning 2

(2)

Översikt övning 2

Klasser

Konstruktorer Destruktorer Arv

Virtuella funktioner Abstrakta klasser

Operatorer

Templateklasser

Templatefunktioner Metaprogrammering Kodningstips

Tentatal

2

(3)

#ifndef _MOVIE_RECORD_

#define _MOVIE_RECORD_

class MovieRecord {  public: 

MovieRecord(); 

MovieRecord(const MovieRecord &mr); 

MovieRecord(std::string title, 

std::string director = "",  int year = 0); 

~MovieRecord(); 

operator=(const MovieRecord &mr); 

friend std::ostream& operator<<(const ostream &os,  const MovieRecord &mr); 

protected: //< Not needed private: 

std::string m_title; 

std::string m_director; 

int m_year; 

}; 

#endif //_MOVIE_RECORD_

Klasser

3

(4)

Konstruktorer

Minnesallokering

automatiskt minne (stacken) dynamiskt minne (heapen)

Initiering av medlemmar

Styrs via initieringslista (kolonlista)

OBS! Följande MÅSTE initieras via kolonlista

const-deklarerade medlemmar referenser

medlemsvariabler av en typ som saknar defaultkonstruktor

Exekvering av kod i konstruktorn

4

(5)

Konstruktorer (cont'd)

Följande konstruktorer skapas automatiskt

Defaultkonstruktor (kör medlemmars defaultkonstruktor)

Kopieringskonstruktor (kör medlemmars kopieringskonstruktor)

Även kopieringsoperatorn (operator=) skapas

”automatiskt”

Kopierar elementvis

5

(6)

Konstruktorer (cont'd)

#include <iostream>

class A {  public: 

std::string str; 

}; 

int main() 

A a; 

std::cout << a.str << std::endl; 

a.str = "Hello"; 

std::cout << a.str << std::endl; 

A b(a);

std::cout << b.str << std::endl;

a.str += ” World”;

b = a;

std::cout << b.str << std::endl;

} 6

(7)

Destruktorer

Kan bara finnas en destruktor Tar aldrig några argument

Defaultdestruktor kör medlemmars destruktor

Tänk på att göra delete och/eller delete[] på rätt sätt i destruktorn

7

(8)

Arv

Animal

­name: std::string = ””

+getName(): std::string

Mule

Donkey Horse

http://www.gnome.org/projects/dia/

http://pigseye.kennesaw.edu/~dbraun/

csis4650/A&D/UML_tutorial/

8

(9)

Arv (cont'd)

Konstruktor

Animal Animal Donkey Animal Donkey Animal Horse Mule

Destruktor

~Animal

~Donkey

~Animal

~Mule

~Horse

~Animal

~Donkey

~Animal

Objekt

Animal Donkey

Mule

9

(10)

Arv (cont'd)

class BaseClass { 

OtherClass& m_ref; 

const int m_c; 

public: 

BaseClass(OtherClass& ref, int c) :  m_ref(ref), m_c(c) {}; 

// BaseClass(OtherClass& ref, int c) : 

// m_c(c), m_ref(ref) {}; //< Warning!

/*...*/ 

}; 

class SubClass: public BaseClass {  public: 

SubClass(OtherClass& ref, int c=4711) :  BaseClass(ref,c) {}; 

// SubClass(OtherClass& ref, int c=4711) :  // m_ref(ref), m_c(c) {}; //< Error!

/*...*/ 

}; 10

(11)

Virtuella funktioner

class A {

void foo() { cout << ”A::foo()” << endl; }

virtual void bar() { cout << ”A::bar()” << endl; } };

class B : public A {

void foo() { cout << ”B::foo()” << endl; } void bar() { cout << ”B::bar()” << endl; } };

int main() {

B b, *bPtr = &b;

A *aPtr = bPtr;

bPtr­>foo();

bPtr­>bar();

aPtr­>foo();

aPtr­>bar();

return 0;

} 11

(12)

Virtuella funktioner (cont'd)

int main() {

B b, *bPtr = &b;

A *aPtr = bPtr;

bPtr­>foo();

bPtr­>bar();

aPtr­>foo();

aPtr­>bar();

return 0;

}

> ./a.out B::foo() B::bar() A::foo() B::bar()

12

(13)

Virtuella funktioner (cont'd)

class A {

void foo() { cout << ”A::foo()” << endl; }

virtual void bar() { cout << ”A::bar()” << endl; } };

class B : public A {

void foo() { cout << ”B::foo()” << endl; } void bar() { cout << ”B::bar()” << endl; } };

Icke virtuella funktioner väljs statiskt vid

kompilering beroende på typ av pekare eller referens.

Virtuella funktioner bestäms dynamiskt under exekvering baserat på objektets faktiska typ.

13

(14)

Virtuella funktioner (cont'd)

Class

int m_id;

std::string name;

...

v­table {...}

V-table

*func1;

*func2;

...

*funcN;

14

(15)

Virtuella funktioner (cont'd)

Virtuella destruktorer

class A {  public: 

~A(){ cout << "~A()" << endl; }  }; 

class B : public A {  public: 

~B(){cout << "~B()" << endl; }  }; 

int main()  {

A* a = new A(); 

A* b = new B(); 

delete a; 

delete b; 

}

Vad är problemet med följande kod?

15

(16)

Virtuella funktioner (cont'd)

Det går ej att skapa en instans av en klass som är "abstrakt". För att göra en klass abstrakt, låt någon funktion i klassen vara "rent"

virtuell (pure virtual).

Ex:

class A {  public: 

virtual foo() = 0; 

. . .  }; 

Klasser som ärver av basklassen MÅSTE implementera de 

funktioner som är "pure virtual" för att man ska kunna instantiera  ett objekt av klassen (annars blir ju även subklassen abstrakt).

16

(17)

Virtuella funktioner (cont'd)

C++

Virtual

virtual void func();

Pure virtual

virtual void func() 

= 0;

Java Default

void func();

Abstract

abstract void func();

17

(18)

Operatorer

class Vec { 

int *m_elem; 

public: 

Vec(){m_elem = new int[10];}

~Vec() { delete[] m_elem; } }; 

int main(){ 

Vec v1; 

Vec v2(v1); 

Vec v3; v3=v2; 

};

Vec::v1 m_elem Vec::v2 m_elem Vec::v3 m_elem

M inne

18

(19)

Operatorer

class Vec { 

int *m_elem; 

public: 

Vec(){m_elem = new int[10];}

~Vec() { delete[] m_elem; } Vec(const Vec& v) { 

m_elem = new int[10]; 

for(int i=0; i<10; i++) 

m_elem[i] = v.m_elem[i]; 

}

Vec& operator=(const Vec& v) {  if(this!=&v){ 

delete[] m_elem; 

m_elem = new int[10]; 

for(int i=0; i<10; i++) 

m_elem[i] = v.m_elem[i]; 

return *this; 

} }; 

Vec::v1 m_elem Vec::v2 m_elem Vec::v3 m_elem

M inne

19

(20)

Operatorer (cont'd)

class Complex { float m_re; 

float m_im; 

public: 

Complex(float re = 0, float im = 0); 

Complex(const Complex &c); 

~Complex(); 

Complex& operator=(const Complex &c); 

Complex& operator++(); //prefix 

Complex& operator++(int); //postfix  Complex& operator­­(); //prefix 

Complex& operator­­(int); //postfix  Complex& operator+=(const Complex &c); 

Complex& operator­=(const Complex &c); 

Complex& operator*=(const Complex &c); 

bool operator==(const Complex &c) const; 

bool operator!=(const Complex &c) const; 

friend Complex operator+(const Complex &c1,  const Complex &c2); 

friend Complex operator­(const Complex &c1,  const Complex &c2); 

friend ostream& operator<<(ostream &os, const Complex &c); 

}; 

20

(21)

Templateklasser

class Stack { private:

int m_stk[STK_SIZE];

int m_top;

public:

Stack() : m_top(0) {};

bool isEmpty() { return (m_top == 0);}

bool isFull() { return (m_top >= STK_SIZE); } bool push(int i)

{

if(isFull()) return false;

m_stk[m_top++] = i;

return true;

}

bool pop(int &i) {

if(isEmpty()) return false;

i = m_stk[­­m_top];

return true;

}

};

21

(22)

Templateklasser (cont'd)

template <typename T> 

class Stack { private:

T m_stk[STK_SIZE];

int m_top;

public:

Stack() : m_top(0) {};

bool isEmpty() { return (m_top == 0);}

bool isFull() { return (m_top >= STK_SIZE); } bool push(const T &o)

{

if(isFull()) return false;

m_stk[m_top++] = o;

return true;

}

bool pop(T &o) {

if(isEmpty()) return false;

o = m_stk[­­m_top];

return true;

}

};

22

(23)

Templateklasser (cont'd)

int main() {

Stack<int> istk; //< Stack of ints

Stack<double> fstk; //< Stack of doubles istk.push(4711);

istk.push(47.11); //< Will be truncated to 47 (Warning) fstk.push(47.11);

fstk.push(4711); //< Will be represented as (double)4711 return 0;

}

23

(24)

Templatefunktioner (cont'd)

template<typename T> inline T max(const T &o1, const T &o2) {

return o1 > o2 ? o1 : o2;

}

int main() {

max(3,6);

max(3.2, ­0.3);

//max(3, 3.2); //< Error max<double>(3, 3.2); //< OK max(”Hejsan”, ”Svejsan”);

return 0;

}

template<> 

const char* max<char*>(const char* &o1, const char* &o2) {

return strcmp(o1,o2) >= 0 ? o1 : o2;

}

24

(25)

Templatefunktioner (cont'd)

Vid kompilering av templates måste alla templatefunktioner och klasser vara definierade innan de används. Detta medför att

templatefunktioner och klasser oftast definieras i .h-filen.

#include ”Stack.h”

int main() {

Stack<int> istk;

//...

return 0;

}

> g++ main.cpp ­o stktst

> ./stktst main.cpp

Stack.cpp finns inte,

implementation i .h-filen

25

(26)

Templatefunktioner (cont'd)

Templates

Återanvända kod (+) Statisk typkontroll (+)

Effektiv implementering (+)

Måste definieras innan användning (-)

Långsam kompilering (-) Stor binärfil (-)

Arv från Object (Java)

Återanvända kod (+) Flexibelt (man kan t ex blanda objekt i en vektor) (+)

Run-time typkontroll (-) Overhead pga V-table etc (-)

Allt måste ärva från ett objekt (-)

26

(27)

Metaprogrammering

template<int N> 

struct fact { 

enum{value=N*fact<N­1>::value}; 

}; 

template<> struct fact<0> {  enum{value=1}; 

}; 

int main() {

cout<< fact<3>::value << endl; 

return 0; 

}

27

(28)

Kodningstips

Var konsekvent

Ge klasser, funktioner och publika

medlemsvariabler beskrivande namn En klass, två filer (.h och .cpp)

Undvik altför “smart” kod Indentera ordentligt

Undvik “one-line-ifs”, använd {}

Undvik nästlade if/for satser

Skriv inte för långa funktioner, dela upp

28

(29)

Kodningstips

Förslag på namngivning

Globala variabler: longVarName Medlemsvariabler: varNam

Lokala variabler: tmp, i, cnt, f, ...

Konstanter: CONST_NAME Klasser: LongClassName

Medlemsfunktioner: longFuncName Globala funktioner: LongFuncName

Statiska medlemsfunktioner: LongFuncName

29

References

Related documents

• Skriv metoden bool move_event(const Date &amp; from, const Date &amp; to, std::string event) som kan flytta händelser i kalendern genom att först plocka ut och sedan lägga

BigNum används när man vill ha en kopia för sidoeffekternas skull (ovanligt) eller när datatypen är så liten att referen- sanrop ger onödigt arbete. const BigNum är faktiskt

Kompi- leringstiderna minskar eftersom beroendena minskar (ta t.ex. extremfallet med endast en .h-fil och en .cpp-fil där allt kompileras om vid varje ändring). Det blir lättare

en C++-klass best˚ ar av en deklaration och en definition deklaration vanligtvis i .h (.hh) och definition i .cpp (.cc) private ¨ ar f¨ orvalt f¨ or funktioner och variabler i

undvik enraders if-satser, anv¨ and alltid { och } undvik om m¨ ojligt n¨ astlade if/for satser skriv inte f¨ or l˚ anga funktioner, dela upp. versionshantera all kod med program

templates (models) used to write type independednt code inheritance is an alternative to shared behaviors. functions and classes parameterized on a

argv[0] är programmets namn (tex /usr/bin/zip eller zip) main() är en global funktion och således inte del av någon klass. main() behöver

Använd std-funktioner, algoritmer etc Optimera där