TDIU20 - Objektorienterad programmering i c++ - föreläsning 6

Relevanta dokument
TDDC76 - Programmering och Datastrukturer

Objektorientering - Arv och polymorfi

TDDC76 - Programmering och Datastrukturer

Objektorientering - Arv och polymorfi. Eric Elfving Institutionen för datavetenskap

Programmering i C++ EDA623 Arv. EDA623 (Föreläsning 6) HT / 42

Innehåll. 1 Kort om dynamisk polymorfism. 2 Arv i C++ 3 Multipelt arv. 4 Något om statisk polymorfism. class Container {

Innehåll. Konstruktorer vid arv Regler för basklassens konstruktor. Konstruktorer vid arv. Konstruktorer vid arv. Konstruktorer vid arv

TDDC76 Programmering och datastrukturer

TDIU20 - Objektorienterad programmering i c++ - föreläsning 4

TDIU01 Programmering i C++

Del2 Klasser, medlemmar och arv Ämnesområden denna föreläsning:

Introduktion till arv

Arv. Objektorienterad och komponentbaserad programmering

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (casting) Implicita Typomvandlingar

Programmering i C++ EDA623 Objektorienterad programutveckling. EDA623 (Föreläsning 5) HT / 33

Innehåll. Pekaren this Självreferens. Klasser Resurshantering, representation. Överlagring av operatorer. Överlagring av operatorer

TDDC76 - Programmering och Datastrukturer

C++ Objektorientering - Klasser. Eric Elfving

Dynamisk bindning och polymorfism

C++ Objektorientering - Klasser. Eric Elfving Institutionen för datavetenskap

Klasser. Kapitel 2. Kapitel 2 - Klasser, medlemmar och arv. Klasser. Klasser Medlemmar Arv

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Del3 Klassanvändning, operatorer och pekare Ämnesområden denna föreläsning:

Programsystem konstruktion med C++ (2D1387) Innehåll. övning 2 klasser och arv

TDDC76 - Programmering och Datastrukturer

Introduktion. Klasser. TDP004 Objektorienterad Programmering Fö 2 Objektorientering grunder

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

5 Arv och dynamisk bindning FIGUR

Klasshierarkier - repetition

TDIU20 - Objektorienterad programmering i c++ - föreläsning 3

TENTAMEN CD5250. Objektorienterad programutveckling med C++, 5p. Datum: , Tid: 14:00-19:00

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Operatoröverlagring. endast operatorsymboler definierade i C++ kan överlagras = += -= *= /= %= ^= &= = <<= >>= < > <= >= ==!= && > ->*, [ ] ( )

Innehåll. Pekare Exempel

Kapitel 3. Synlighet. Kapitel 3 - Klassanvändning, operatorer och pekare. Synlighet

Föreläsning 8. Arv. Arv (forts) Arv och abstrakta klasser

Trädtraversering. Binärt träd. Trädtraversering djupet-först. Trädtraversering bredden-först

Skapa, kopiera och destruera klassobjekt

Kapitel 6 - Undantag

Innehåll. Pekare Exempel

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Generiska konstruktioner. Kursbokens kapitel 13

Objektorienterad Programmering (TDDC77)

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Programsystemkonstruktion med C++: Övning 2. Karl Palmskog september 2010

Objektorienterade programmeringsspråk. Objektorienterade språk. Den objekt-orienterade modellen. Jämför med icke-oo

Arv bakgrund (kap. 9)

Tentamen EDAF30 Programmering i C++

Synlighet. Namespace Scope-operatorn Klasser Vänner

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

UML. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

TDIU01 - Programmering i C++, grundkurs

Kopiering av objekt i Java

Programsystemkonstruktion med C++

Outline. Objektorienterad Programmering (TDDC77) Att instansiera en klass. Objekt. Instansiering. Åtkomst. Abstrakt datatyp.

Innehåll. Introduktion till objektorientering. OOP (objektorienterad programmering) Objekt, instanser, klasser

DAT043 - Föreläsning 7

KLASSER. Inkapsling Abstrakt datatyp Public och private. Klassmedlemmar Datamedlemmar Exempel Funktionsmedlemmar

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

Lektionsuppgifter. TDDI14 Objektorienterad programmering. Lektionsplanering Lektion Lektion Lektion

Programmering i C++ EDA623 Mallar. EDA623 (Föreläsning 12) HT / 29

Innehåll. Resource handles. Resurshantering. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 7. Resurshantering, Felhantering

Övriga byggstenar. Övriga byggstenar. Några tips under programutveckling. Beroenden Pekare till funktioner Typkonvertering

Objektorienterad Programkonstruktion. Föreläsning 4 8 nov 2016

TDIU01 - Programmering i C++, grundkurs

UML. Klassdiagr. Abstraktion. Relationer. Överskugg. Överlagr. Aktivitetsdiagram Typomv. Typomv. Klassdiagr. Abstraktion. Relationer.

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

OOP Objekt-orienterad programmering

Polymorfi. Objektorienterad och komponentbaserad programmering

I STONE. I Variabler, datatyper, typkonvertering. I Logiska och matematiska uttryck. I Metoder-returvärde och parametrar. I Villkorssatser if/else

Outline. Objektorienterad Programmering (TDDC77) Signatur. Klassen calculator. Överlagring (overloading) Arv (inheritance) Ahmed Rezine

Konstruktion av klasser med klasser

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

Objektorienterad programmering Föreläsning 12. Copyright Mahmud Al Hakim

Objektorienterad Programmering (TDDC77)

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (type casts) Explicita, namngivna typomvandlingar (C++-11)

1 Klasser och objektorientering Vad är objektorientering?

F8: Typkonvertering i C++

Programmering i C++ EDAF30 Dynamiska datastrukturer. EDAF30 (Föreläsning 11) HT / 34

Det objektorienterade synsättet. Objekt. Datorprogrammet kan uppfattas som en slags modell av den verklighet programmet skall samverka med.

Föreläsning 4. Klass. Klassdeklaration. Klasser Och Objekt

Problemet. Vi har sett att vi kan ersätta de metoder vi ärver från överklassen med egen funktionalitet (polymorfism)

Vad är en klass? Övning 2. Konstruktorer. ffl copy-konstruktorn tar en instans av klassen som. ffl default-konstruktorn tar inga argument och kan

Innehåll. Användardefinierade typer. Användardefinierade typer Kategorier. Konstruktorer. Konstruktorer Två sätt att skriva initiering av medlemmar

Tillämpad programmering

*:85/ID200V C++ HT07. Föreläsning 8 Medlemspekare Undantagshantering Namnrymder

Föreläsningsmaterial (Arv) Skrivet av Andreas Lund

Tentamen i TDP004 Objektorienterad Programmering Teoretisk del

Klasser. Det är egentligen nu som kursen i programmeringsteknik börjar..., s k objektorienterad programmering.

Objektorienterad Programmering (TDDC77)

Tillämpad programmering

UML. Översikt UML. Relationer mellan klasser. A är ett aggregerat av B:n. Kontor aggregat av Enheter. 12 olika diagramtyper, bl.a.

Classes och Interfaces, Objects och References, Initialization

1 Namnkontroll (NameControl)

allokeras på stacken dynamiskt new delete

Minneshantering. Minneshantering. Minneshantering. Undvik pekare

TDDI14 Objektorienterad programmering

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Transkript:

TDIU20 - Objektorienterad programmering i c++ - föreläsning 6 Pontus Haglund och Gustav L'estrade anpassade slides av Klas Arvidsson Department of Computer and information science

1 Arv (Specialisering) 2 Bindning, static/dynamic 3 Cast av pekare och referenser 4 UML 5 Övriga hänsynstaganden 6 Bonus

2 / 50 Vad gjorde vi förra gången? Speciella medlemsfunktioner Konstruktor Destruktor Kopiering Flytt När? (Reglerna för 0, 3 och 5/6) Vad är korrekt kopiering? Vad är korrekt flytt?

3 / 50 Dagens föreläsning Fokus på objektorientering Arv (specialisering) Relationer Smått och gott i mån av tid

1 Arv (Specialisering) 2 Bindning, static/dynamic 3 Cast av pekare och referenser 4 UML 5 Övriga hänsynstaganden 6 Bonus

5 / 50 Person Vi låtsas att en person har ett namn och ett telefonnummer. Hur kan vi representera en person? Med en klass så klart!

6 / 50 Person // Person.h class Person public: Person(std::string n, std::string p); std::string get_phone () const return phone; } void print_info(ostream& os) const; private: string name; string phone; }; // Person.cc Person::Person(string n, string p): namen}, phonep} } void Person::print_info(ostream& os) const os << "Name: " << name << '\n'; os << "Phone: " << phone << endl; }

7 / 50 Employee Vi vill nu skapa en anställd. En anställd är en person med lön och arbetstelefon. Hur skapar vi den klassen när vi redan har en person? Vi kan kopiera och klistra till helt ny klass Employee. Det innebär att allt framtida arbete med Person-klassen manuellt måste dupliceras till Employee. Vi kan låta en ny Employee-klass innehålla en Person som datamedlem. Det innebär att vi måste skapa nya funktioner i Employee för att komma åt allt i Person.

8 / 50 Arv från / Specialisering av Person Vi kan använda arv för att berätta för kompilatorn att en ny klass Employee automatiskt är allt som en Person är. Person blir basklass och Employee blir härledd klass (alternativt subklass eller specialisering): class Employee : public Person public: Employee(string n, string p, string w, int s); string get_phone () const; string get_home_phone () const; string get_work_phone () const return work_phone; } int salary () const; private: string work_phone; int salary; };

9 / 50 Anrop av basklass från subklass Employee(string n, string p, string w, int s) : Personn, p}, work_phonew}, salarys} Datamedlemmarna name och phone är en del av basklassen. Det är därför praktiskt att anropa basklassens konstruktor för att initiera de datamedlemmarna

10 / 50 Anrop av basklass från subklass En härledd klass har direkt alla datamedlemmar och medlemsfunktioner som finns i basklassen. Det går även att explicit ange att basklassens medlem ska användas. Men inte ens en härledd klass har tillgång till basklassens privata medlemmar! string Employee :: get_phone () const return Person :: get_phone () + ", " + work_phone; } string Employee :: get_home_phone () const return phone; // Compilation error, private to Person! }

11 / 50 Åtkomst av datamedlemmar i subklass Vi kan i basklassen ge härledda klasser tillgång till medlemmar med nyckelordet protected! class Person public:... private: // endast för klassen själv string name; protected: // endast för klassen själv och härledda klasser string phone; };

12 / 50 Public/Private/Protected arv Vi skrev ovan public när vi skapade subklassen. Varför? class Employee : public Person Vad gör det och andra nyckelord? public: medlemmar i basklassen behåller deklarerat skydd protected: public medlemmar i basklassen blir protected i härledd klass private: alla medlemmar i basklassen blir private i härledd klass

13 / 50 Public/Private/Protected arv forts Notera att privata medlemmar i basklassen aldrig är åtkomliga i subklassen. Lämnar du tomt väljs privat arv som standard. Var som vanligt alltid explicit

1 Arv (Specialisering) 2 Bindning, static/dynamic 3 Cast av pekare och referenser 4 UML 5 Övriga hänsynstaganden 6 Bonus

15 / 50 Statisk bindning (static binding) I C++ används statisk bindning om inget annat anges. Det innebär att datatypen som anges i programkoden avgör vilken funktion som anropas. Person kim"kim", "2146"}; Employee sam"sam", "2490", "1234", 40000}; Person& refsam}; cout << kim.get_phone () << endl; cout << sam.get_phone () << endl; cout << sam.get_work_phone () << endl; cout << ref.get_phone () << endl; cout << ref.get_work_phone () << endl; sam.print_info(cout ); kim.print_info(cout );

16 / 50 Statisk bindning (static binding) I C++ används statisk bindning om inget annat anges. Det innebär att datatypen som anges i programkoden avgör vilken funktion som anropas. Person kim"kim", "2146"}; Employee sam"sam", "2490", "1234", 40000}; Person& refsam}; cout << kim.get_phone () << endl; // 2146 cout << sam.get_phone () << endl; // 2490, 1234 cout << sam.get_work_phone () << endl; // 1234 cout << ref.get_phone () << endl; // 2490 cout << ref.get_work_phone () << endl; // Compilation error! sam.print_info(cout ); // Sams uppgifter skrivs ut på cout kim.print_info(cout ); // Kims uppgifter skrivs ut på cout

17 / 50 Välj / välj bort specifika basklassmetoder Det går att välja och vraka vilka medlemsfunktioner från basklasserna som ska finnas i den härledda klassen // Tillfällig vikarie class Substitute : public Employee public: using Employee :: Employee; // Ger konstruktor motsvarande Employee using Person :: get_phone (); // Väljer versionen i Person string get_work_phone () const = delete; }; Substitute s"toni", "4711", "", 60000}; s.get_phone (); // The version in Person s.get_work_phone (); // Compilation error!

18 / 50 Subklass har alla datatyper En härledd klass är både sin egen datatyp och basklassens datatyp! En vikarie kan alltså användas som Person, Employee och Substitute. Vi bör dock tänka oss för vid tilldelningar! Person p"p", "1"}; Substitute s"s", "2", "3", 0}; p = s; // Ok, men ger slicing Employee& e = s; // Ok Person* pp = &s; // Ok Substitute v = e; // Compilation error!

19 / 50 Regler för typer En referens av typ T kan hänvisa till en typ härledd från T. En referens av typ T kan inte hänvisa till en bastyp av T. Ovanstående gäller även pekare! Ett objekt av typ T rymmer aldrig en härledd typ och kan inte lagra enbart en bastyp.

20 / 50 Exempel std::ostream std::ostream är basklassen för alla utströmmar Genom använda en std::ostream som parameter kan funktioner ta valfri härledd utströmtyp void print_hello(ostream& os) os << "Hej" << endl; } ofstream ofs"hello.txt"}; ostringstream oss; print_hello(ofs); // print to file print_hello(oss); // print to stringstream print_hello(cout ); // print to standard output print_hello(cerr ); // print to standard error

21 / 50 Exempel std::exception std::exception är basklassen för alla standardundantag Genom att fånga en basklassreferens kommer vi att fånga även alla undantag härledda från den fångade basklasstypen try // Kod som kastar undantag... } catch( logic_error& e) // Fångar logic_error i första hand } catch( exception& e ) // Fångar klasser härledda från exception i andra hand }

22 / 50 Flera olika typer av anställda i en lista? En pekare till Employee kan peka på härledda klasser Vilken funktion anropas? vector <Employee*> v; v.push_back(new Employee...}); v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...}); for ( Employee const* e : v ) cout << e->salary () << endl; }

23 / 50 Implementation av programmer class Programmer : public Employee public: Programmer (..., double e = 1.0) : Employee (...), expertisee} } int salary () const return salary * expertise; } private: double expertise; };

24 / 50 Implementation av Consultant class Consultant : public Employee public: Consultant (..., int p, int h) : Employee (...), hour_payp}, hours_workedh} } int salary () const return salary + hour_pay * hours_worked; } private: int hour_pay; int hours_worked; };

25 / 50 Implementation av CEO class CEO : public Employee public: CEO (..., int bonus = 1000000) Employee (...), bonusbonus} } int bonus () const return bonus; } int salary () const return salary + bonus; } private: int bonus; };

26 / 50 Löneberäkning av olika kategorier Statiskt bindning är default Med andra ord behöver vi göra något för att salary skall tas av subklassen! vector <Employee*> v; v.push_back(new Employee...}); v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...}); for ( Employee const* e : v ) // Employee::salary() anropas! cout << e->salary () << endl; }

27 / 50 Dynamisk bindning till räddning! virtual, override och final class Employee : public Person //... virtual int salary () const; //... protected: int salary; }; class CEO : public Employee //... int salary () const override; //... };

28 / 50 Vtable Basklassen måste med virtual ange om härledda klasser har en egen variant en funktion! Den härledda klassen ska med override ange att den ersätter basklassens variant, eller final.

29 / 50 Polymorfi När funktionen är virtual får vi dynamisk bindning (polymofi) Nu är det medlemsfunktionen som finns i det objekt som pekas ut som anropas vector <Employee*> v; v.push_back(new Employee...}); v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...}); for ( Employee const* e : v ) cout << e->salary () << endl; }

30 / 50 Pekare och referenser - dynamisk typ Vi kan endast ha dynamisk bindning(polymorfi) när vi anropar en virtual funktion från: en basklasspekare en basklassreferens

1 Arv (Specialisering) 2 Bindning, static/dynamic 3 Cast av pekare och referenser 4 UML 5 Övriga hänsynstaganden 6 Bonus

32 / 50 Kommer ni ihåg dynamic_cast()? Pekare Ibland vill vi kunna ta reda på om en pekare egentligen pekar på en viss subklass: for ( Employee const* e : v ) CEO* ceo dynamic_cast <CEO*>(e) }; //Kan bli nullptr if ( ceo!= nullptr ) cout << ceo->bonus (); } cout << e->salary () << endl; }

33 / 50 Kommer ni ihåg dynamic_cast()? Pekare Ibland vill vi kunna ta reda på om en referens egentligen hänvisar till en viss subklass: void print_salary( Employee const& e ) cout << e.salary (); CEO& ceo dynamic_cast <CEO&>( e ) }; // may throw std::bad_cast cout << ceo.bonus (); } try CEO ceo... }; print_salary(ceo); } catch(std:: bad_cast const& e) cerr << e.what () << endl; }

1 Arv (Specialisering) 2 Bindning, static/dynamic 3 Cast av pekare och referenser 4 UML 5 Övriga hänsynstaganden 6 Bonus

35 / 50 Universal modelling language Grafiskt språk Används för att beskriva system bl.a. objektorienterade system Vi ta upp 4 relationer: Arv: En Person är en Människa med allt det innebär. Komposition: En Person har en Kropp. Aggregation: En Person kan ha Klädesplagg. Association: En Person kan använda en Hyrbil.

36 / 50 CRC-kort (analysmetod) Vid objektorienterad analys kan vi använda CRC-kort för att komma fram till de klasser som behövs. Samtidigt definerar vi klassens ansvar och dess samarbetspartner. Man kan exempelvis använda postit-lappar och skriva: Class (klassens namn) Responsibility (Klassens ansvarsområde) Collaborators (samarbetspartners till klassen, hjälpklasser)

37 / 50 Uml resultat av analys Human Cloth Person Body RentalCar

38 / 50 Mer detaljer När de klasser vi behöver är indentifierade kan vi specificera dem i större detalj. Datamedlemmar, medlemsfunktioner ochd dess åtkomst specificeras: + public - private # protected : typ, returtyp eller datatyp

39 / 50 Mer detaljerat diagram Human #iq: int Cloth Person -name: std::string -cloths: std::vector<cloth*> -body: Body +drive(c:rentalcar const&): bool RentalCar Body -height: double +groom(): void

40 / 50 uml som kod class Person : public Human // inheritance, is public: Person () : Human}, body}, clothing } } void put_on(cloth* c); void drive(rentalcar &); // association, uses a private: Body body; // composition, always part of vector <Cloth*> clothing; // aggregation, can come and go };

1 Arv (Specialisering) 2 Bindning, static/dynamic 3 Cast av pekare och referenser 4 UML 5 Övriga hänsynstaganden 6 Bonus

42 / 50 Abstrakt klass = 0 En basklass är abstrakt om minst en medlemsfunktion är pure virtual. Om så är fallet måste alla subklasser implementera den funktionen. class Employee : public Person // abstract class due to... //... virtual int salary () const = 0; // pure virtual function //... }; Employee e...}; // Compilation error, incomplete class Employee* e new CEO...}};

43 / 50 Minnehantering, destruktor Som vanligt måste varje new motsvaras av en delete. Men hur anropar vi rätt destruktor? vector <Employee*> v; v.push_back(new Employee...}); // Compilation error, incomplete class v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...}); for ( Employee const* e : v ) delete e; // Endast destruktorn för Employee! }

44 / 50 Virtuell destruktor Precis som medlemsfunktioner kan vara virtuella så vi hittar rättfunktion kan vi göra samma sak med destruktorn: class Employee : public Person public: //... virtual ~Employee () = default; //... } for ( Employee const* e : v ) delete e; // Varje destruktor anropas, den mest härledda först! }

45 / 50 Egen undantagsklass Kan skapa egna udantag genom att ärva av de existerande standardundantaget class Stack_Error : public std:: logic_error public: // Använd logic_errors konstruktor using std::logic_error::logic_error; }; class Code_Error : public std:: exception public: // Egen konstruktor Code_Error(int code) noexcept : exception }, codecode} } const char* what () const noexcept return ""; } int get_error_code () const return code; } private: int code; };

1 Arv (Specialisering) 2 Bindning, static/dynamic 3 Cast av pekare och referenser 4 UML 5 Övriga hänsynstaganden 6 Bonus

47 / 50 Smarpekare Finns två typer av smartpekare i c++17. unique_ptr och shared_ptr vector <unique_ptr <Employee >> v; v.push_back(unique_ptr <Employee >new Employee...}});//Samma som under v.push_back(make_unique <Employee >(...)); // men det här är säkrare v.push_back(make_unique <CEO >(...)); //... } // Vectors destruktor kommer köra destruktorn för varje Employee

48 / 50 Interface. Ibland vill vi bara bestämma vilka operationer som ska gå att utföra på en viss typ av objekt. Vi bestämmer objektets gränssnitt (interface). I C++ kan vi då skapa en helt abstrakt klass (enbart virtual funktioner): class Stack_Interface public: virtual void push(int value ) = 0; virtual void pop () = 0; virtual int& top () = 0; virtual int top() const = 0; virtual bool empty () const = 0; }; class Linked_Stack : public Stack_Interface... } class Vector_Stack : public Stack_Interface... } // Denna funktion tar vilken stack som helst! void use_stack(stack_interface& stack ); Varför ska dessa funktioner vara pure virtual?

49 / 50 Interface. Ibland vill vi bara bestämma vilka operationer som ska gå att utföra på en viss typ av objekt. Vi bestämmer objektets gränssnitt (interface). I C++ kan vi då skapa en helt abstrakt klass (enbart virtual funktioner): class Stack_Interface public: virtual void push(int value ) = 0; virtual void pop () = 0; virtual int& top () = 0; virtual int top() const = 0; virtual bool empty () const = 0; }; class Linked_Stack : public Stack_Interface... } class Vector_Stack : public Stack_Interface... } // Denna funktion tar vilken stack som helst! void use_stack(stack_interface& stack ); För att de alltid ska implementeras av subklassen!

50 / 50 NVI icke-virtuellt gränssnitt Ibland rekommenderas att virtual funktioner placeras privat. Det gör det enklare att ändra hur klassen löser problem internt utan att ändra på hur den används. class Stack_Interface public: void push(int value ); void pop (); //... private: // prefix undviker krock med publika medlemsfunktioner virtual void v_push(int value ); virtual void v_pop (); //... };

www.liu.se