Föreläsningsanteckningar OOP-föreläsning 10, tisdag 3 oktober 2006 ================================================================= Idag ==== 1. Forts: Geometriska figurer 2. Kan ni hitta felet? Och vad händer? 3. Ett problem inom objektorienterad design 4. Geometriska figurer med C++/CLI i Visual Studio 2005 5. Multipelt arv 6. Ofta är aggregat ("består av") bättre än multipelt arv 7. I/O med iostream 8. Kl 14:30: Valinformation för SoS 1. Forts: Geometriska figurer ============================= figurer-2.cpp ------------- #include #include #include using namespace std; //---------------------------------------------------------- class FIGUR { private: string namn; FIGUR* next; static FIGUR* first; public: FIGUR(string namn); virtual void skriv(); virtual double area() = 0; FIGUR* get_next(); static double total_area(); }; FIGUR* FIGUR::first = NULL; FIGUR::FIGUR(string namn) { this->namn = namn; next = first; first = this; } void FIGUR::skriv() { cout << "Namn: " << namn << endl; } double FIGUR::total_area() { FIGUR* p = first; double summa = 0; while (p != NULL) { summa += p->area(); p = p->next; } return summa; } //---------------------------------------------------------- class REKTANGEL : public FIGUR { private: double bredd, hojd; public: REKTANGEL(string namn, double bredd, double hojd); void skriv(); double area(); }; REKTANGEL::REKTANGEL(string namn, double bredd, double hojd) : FIGUR(namn) { this->bredd = bredd; this->hojd = hojd; } double REKTANGEL::area() { return bredd * hojd; } void REKTANGEL::skriv() { FIGUR::skriv(); cout << "Bredd: " << bredd << ", höjd: " << hojd << endl; } //---------------------------------------------------------- class CIRKEL : public FIGUR { private: double radie; static const double PI; public: CIRKEL(string namn, double radie); void skriv(); double area(); }; const double CIRKEL::PI = 3.1415926535; CIRKEL::CIRKEL(string namn, double radie) : FIGUR(namn) { this->radie = radie; } double CIRKEL::area() { return PI * radie * radie; } void CIRKEL::skriv() { FIGUR::skriv(); cout << "Radie: " << radie << endl; } //---------------------------------------------------------- class KVADRAT : public REKTANGEL { public: KVADRAT(string namn, double sida); void skriv(); }; KVADRAT::KVADRAT(string namn, double sida) : REKTANGEL(namn, sida, sida) { } void KVADRAT::skriv() { FIGUR::skriv(); cout << "Sida: " << sqrt(area()) << endl; // sqrt, eftersom sidomåtten är privata i REKTANGEL } //---------------------------------------------------------- int main() { // FIGUR f1("f1"); -- Går inte, för FIGUR är en abstrakt klass REKTANGEL r1("r1", 10, 17.3); r1.skriv(); cout << "r1:s area = " << r1.area() << endl; CIRKEL c1("c1", 10); c1.skriv(); cout << "c1:s area = " << c1.area() << endl; KVADRAT k1("k1", 10); k1.skriv(); cout << "k1:s area = " << k1.area() << endl; KVADRAT* k2p = new KVADRAT("k2", 12.5); k2p->skriv(); cout << "k2:s area = " << k2p->area() << endl; FIGUR* k3p = new KVADRAT("k3", 12.5); k3p->skriv(); cout << "k3:s area = " << k3p->area() << endl; cout << "Sammanlagda arean = " << FIGUR::total_area() << endl; } Utmatning --------- Namn: r1 Bredd: 10, höjd: 17.3 r1:s area = 173 Namn: c1 Radie: 10 c1:s area = 314.159 Namn: k1 Sida: 10 k1:s area = 100 Namn: k2 Sida: 12.5 k2:s area = 156.25 Namn: k3 Sida: 12.5 k3:s area = 156.25 2. Kan ni hitta felet? Och vad händer? ====================================== void KVADRAT::skriv() { FIGUR:skriv(); cout << "Sida: " << sqrt(area()) << endl; } Varning från kompilatorn ------------------------ figurer-1.cpp: In member function `void KVADRAT::skriv()': figurer-1.cpp:85: warning: label `FIGUR' defined but not used 3. Ett problem inom objektorienterad design =========================================== Är en kvadrat verkligen en rektangel? (Även känt som: Är en cirkel verkligen en ellips?) 4. Geometriska figurer med C++/CLI i Visual Studio 2005 ======================================================= (Man kan skapa konsolprojekt även för .NET) CLI_konsol_text.cpp ------------------- #include "stdafx.h" #include using namespace System; //---------------------------------------------------------- ref class FIGUR abstract { private: System::String^ namn; FIGUR^ next; static FIGUR^ first = nullptr; public: FIGUR(System::String^ namn); virtual void skriv(); virtual double area() = 0; static double total_area(); }; FIGUR::FIGUR(System::String^ namn) { this->namn = namn; next = first; first = this; } void FIGUR::skriv() { Console::WriteLine(L"Namn: " + namn); } double FIGUR::total_area() { FIGUR^ p = first; double summa = 0; while (p != nullptr) { summa += p->area(); p = p->next; } return summa; } //---------------------------------------------------------- ref class REKTANGEL : public FIGUR { private: double bredd, hojd; public: REKTANGEL(System::String^ namn, double bredd, double hojd); virtual void skriv() override; virtual double area() override; }; REKTANGEL::REKTANGEL(System::String^ namn, double bredd, double hojd) : FIGUR(namn) { this->bredd = bredd; this->hojd = hojd; } double REKTANGEL::area() { return bredd * hojd; } void REKTANGEL::skriv() { FIGUR::skriv(); Console::WriteLine(L"Bredd: " + bredd + L", höjd: " + hojd); } //---------------------------------------------------------- ref class CIRKEL : public FIGUR { private: double radie; static const double PI = 3.1415926535; public: CIRKEL(System::String^ namn, double radie); virtual void skriv() override; virtual double area() override; }; CIRKEL::CIRKEL(System::String^ namn, double radie) : FIGUR(namn) { this->radie = radie; } double CIRKEL::area() { return PI * radie * radie; } void CIRKEL::skriv() { FIGUR::skriv(); Console::WriteLine(L"Radie: " + radie); } //---------------------------------------------------------- ref class KVADRAT : public REKTANGEL { public: KVADRAT(System::String^ namn, double sida); virtual void skriv() override; }; KVADRAT::KVADRAT(System::String^ namn, double sida) : REKTANGEL(namn, sida, sida) { } void KVADRAT::skriv() { FIGUR::skriv(); Console::WriteLine(L"Sida: " + sqrt(area())); // sqrt, eftersom sidomåtten är privata i REKTANGEL } //---------------------------------------------------------- int main(array ^args) { // FIGUR f1(L"f1"); -- Går inte, för FIGUR är en abstrakt klass REKTANGEL r1(L"r1", 10, 17.3); r1.skriv(); Console::WriteLine(L"r1:s area = " + r1.area()); CIRKEL c1(L"c1", 10); c1.skriv(); Console::WriteLine(L"c1:s area = " + c1.area()); KVADRAT k1(L"k1", 10); k1.skriv(); Console::WriteLine(L"k1:s area = " + k1.area()); KVADRAT^ k2p = gcnew KVADRAT(L"k2", 12.5); k2p->skriv(); Console::WriteLine(L"k2:s area = " + k2p->area()); FIGUR^ k3p = gcnew KVADRAT(L"k3", 12.5); k3p->skriv(); Console::WriteLine(L"k3:s area = " + k3p->area()); Console::WriteLine(L"Sammanlagda arean = " + FIGUR::total_area()); } Körexempel ---------- Namn: r1 Bredd: 10, höjd: 17,3 r1:s area = 173 Namn: c1 Radie: 10 c1:s area = 314,15926535 Namn: k1 Sida: 10 k1:s area = 100 Namn: k2 Sida: 12,5 k2:s area = 156,25 Namn: k3 Sida: 12,5 k3:s area = 156,25 Sammanlagda arean = 899,65926535 Press any key to continue . . . 5. Multipelt arv ================ Ur platta-1.cpp --------------- class ELAPPARAT { private: int me; // Märkeffekt double pos; // KNapposition 0.0-1.0 public: ELAPPARAT(int me, double pos); double effekt(); }; ELAPPARAT::ELAPPARAT(int me, double pos) { this->me = me; this->pos = pos; } double ELAPPARAT::effekt() { return me*pos; } //---------------------------------------------------------- class PLATTA : public ELAPPARAT, public CIRKEL { public: PLATTA(int me, double pos, string namn, double radie); double area_effekt(); }; PLATTA::PLATTA(int me, double pos, string namn, double radie) : ELAPPARAT(me, pos), CIRKEL(namn, radie) { } double PLATTA::area_effekt() { return effekt() / area(); } //---------------------------------------------------------- int main() { PLATTA p1(1500, 0.5, "p1", 0.15); cout << "Plattans area: " << p1.area() << endl; cout << "Plattans areaeffekt: " << p1.area_effekt() << " W/m2" << endl; } 6. Ofta är aggregat ("består av") bättre än multipelt arv ========================================================= Ur platta-2.cpp --------------- class PLATTA { private: ELAPPARAT ea; CIRKEL c; public: PLATTA(int me, double pos, string namn, double radie); double area_effekt(); double area(); }; PLATTA::PLATTA(int me, double pos, string namn, double radie) : ea(me, pos), c(namn, radie) { } double PLATTA::area_effekt() { return ea.effekt() / c.area(); } double PLATTA::area() { return c.area(); } //---------------------------------------------------------- int main() { PLATTA p1(1500, 0.5, "p1", 0.15); cout << "Plattans area: " << p1.area() << endl; cout << "Plattans areaeffekt: " << p1.area_effekt() << " W/m2" << endl; } 7. I/O med iostream =================== 8. Kl 14:30: Valinformation för SoS ===================================