Kontenery, iteratory, Klasy, Dziedziczenie i Wskaźniki.

0

Cześć bawię się klasami i kontenerami, jako że uczę się tego na studia muszę robić to zgodnie ze standardami nauczycieli artefaktów nie używać "for Range". Wiem że to dla mojego dobra dla tego ostro ćwiczę by ogarniać.

Teraz zastanawiam się w jaki sposób wyświetlić kontener w klasie bazowej - przy okazji co robię źle i może co poprawić :P gównie chodzi o main i metode - wyswietlkontener() ale wszelkie info i propozycje tyczące się dziedziczenia i budowy klas też będą mile widziane.

Ma ona wyświetlać pole i obwód klas zapisanych w kontenerze.

  1. Pytanie czy
//Z tego co rozumiem to tutaj przekazuje do kontenera adres na klasę ?
Kwadrat * kw = new Kwadrat(2, "FajnyK");
bf.dodajdokontenera(kw);

//Jakbym zrobił tak robię to samo.
bf.dodajdokontenera(new Kwadrat(2, "FajnyK"));
  1. Rozumiem że w wyswietlkonterner() dostaje adres na klasę bazową w której znajduje się kontener i teraz muszę tak wyciągnąć dane by móc pracować i wyświetlać je z kontenera - i tu mam problem, a może i wcześniej coś zmienić bo inaczej powinienem to przekazać itp. itd.
void wyswietlkontener(BazaFigur & b) {
        vector<BazaFigur*>::iterator it;
        for (it=(b.kontenerfigur).begin(); it!=(b.kontenerfigur).end(); it++) {
            cout << *it << endl;
        }
    }

main.cpp

#include <iostream>
#include "bazafigur.h"

using namespace std;

int main() {
	BazaFigur bf;
	Kwadrat * kw = new Kwadrat(2, "FajnyK");
	Prostokat * pr = new Prostokat(2, 3, "FajnyP");
	Kolo * ko = new Kolo(2, "FajnyKo");
	Trojkat * tr = new Trojkat(2, 3, "FajnyTr");
	bf.dodajdokontenera(kw);
	bf.dodajdokontenera(pr);
	bf.dodajdokontenera(ko);
	bf.dodajdokontenera(tr);
	bf.wyswietlkontener(bf);
	return 0;
}

bazafigur.h

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <math.h>

const double pi = 3.14;

using namespace std;

class BazaFigur {
protected:
	string nazwa;
	vector<BazaFigur*>kontenerfigur;
public:
	BazaFigur(){
	}

	BazaFigur(string nazwa): nazwa(nazwa){
		cout << "Tworze (obiekt) figure " << nazwa << endl;
	}

	virtual ~BazaFigur() {
		for (BazaFigur * b : kontenerfigur) {
			delete b;
		}
		cout << "Zegnaj " << nazwa << endl;
	}
	virtual double pole() {
		return 0;
	}
	
	virtual double obwod() {
		return 0;
	}
	

	void dodajdokontenera(BazaFigur * b) {
		kontenerfigur.push_back(b);
	}

	void wyswietlkontener(BazaFigur & b) {
		vector<BazaFigur*>::iterator it;
		for (it=(b.kontenerfigur).begin(); it!=(b.kontenerfigur).end(); it++) {
			cout << *it << endl;
		}
	}

};

class Kwadrat : public BazaFigur {
protected:
	double a;
public:
	Kwadrat(double a, string nazwa) : BazaFigur(nazwa), a(a) {
		cout << "Tworze (obiekt) kwadrat " << nazwa << endl;
	}
	
	~Kwadrat() {
		cout << "Zegnaj (obiekt) kwadrat " << nazwa << endl;
	}

	virtual double pole() {
		return a*a;
	}
	
	virtual double obwod() {
		return a * 4;
	}
};


class Prostokat : public Kwadrat {
protected:
	double b;
public:
	Prostokat(double b, double a, string nazwa) : Kwadrat(a, nazwa), b(b) {
		cout << "Tworze (obiekt) prostokat " << nazwa << endl;
	}

	~Prostokat() {
		cout << "Zegnaj (obiekt) prostokat " << nazwa << endl;
	}

	virtual double pole() {
		return a * b;
	}

	virtual double obwod() {
		return (2 * a) + (2 * b);
	}
};

class Kolo : public BazaFigur {
protected:
	double r;
public:
	Kolo(double r, string nazwa) : BazaFigur(nazwa), r(r) {
		cout << "Tworze (obiekt) kolo " << nazwa << endl;
	}

	~Kolo() {
		cout << "Zegnaj (obiekt) kolo " << nazwa << endl;
	}

	virtual double pole() {
		return pi * pow(r, 2);
	}

	virtual double obwod() {
		return 2 * pi * r;
	}
};

class Trojkat : public Kolo {
protected:
	double h;
public:
	Trojkat(double h, double r, string nazwa) : Kolo(r, nazwa), h(h) {
		cout << "Tworze (obiekt) trojkat " << nazwa << endl;
	}

	~Trojkat() {
		cout << "Zegnaj (obiekt) trojkat " << nazwa << endl;
	}

	virtual double pole() {
		return 1 / 2 * r*h;
	}

	virtual double obwod() {
		return h*2;
	}
};

Z góry dzięki za pomoc! Jak przez to przebrnę, przebije pewną barierę mentalna na temat wskaźników i klas :P

4

Tak na szybko, w kodzie brzydkie są:

  1. wszystkie figury są kontenerami. WTF
  2. using namespace std; w nagłówku. Ogółem tego się unika, a już na pewno w nagłówkach
  3. nagie new i delete. Masz kontenery, masz smart pointery, masz inne narzędzia
  4. zaraz zaraz... trójkąt jest kołem?! prostokąt kwadratem?! WTF 2

Jeśli chodzi o wyświetlenie kontenera, zdefiniuj operator<<(ostream&, Baza const&) i z niego wywołaj metodę wirtualną

ostream& operator<<(ostream& o, Baza const& b) {
	return b.put(o);
}

w interfejsie:

virtual ostream& put(ostream&) const =0;

i np. w kwadracie

virtual ostream& put(ostream& o) const override {
	return o << "Kwadrat[" << a << "]";
}
0
  1. Rzeczywiście nie miało to sensu.

  2. Już zostawię - ale dobrze wiedzieć.

  3. Nie rozumiem ;P

  4. No Kolo ma zmienną r kwadrat używa natomiast r i h. Mimo że są figurami różnymi no to nie widzę problemu żeby mogły dziedziczyć. Przykład z Kwadratem i Prostokątem jest typowym do nauki ze względu na dziedziczenie zmiennych, konstruktory, destruktory i metody - żeby zobaczyć o co chodzi z przesłanianiem, destruktorem virtual itp.

  5. Jesteś wstanie mi pomóc z tym przeciążaniem - bo kombinuje nie potrafię dojść do tego.

bazafigur.h

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <math.h>

using namespace std;

const double pi = 3.14;

class Ksztalt {
protected:
	string nazwa;
public:
	Ksztalt(string nazwa) : nazwa(nazwa) {
		cout << "Tworze (obiekt) figure " << nazwa << endl;
	}

	~Ksztalt() {
	cout << "Zegnaj " << nazwa << endl;
	}

	string getName() {
		return nazwa;
	};

	virtual double pole() = 0;
	virtual double obwod() = 0;
};

class Kwadrat : public Ksztalt {
protected:
	double a;
public:
	Kwadrat(double a, string nazwa) : Ksztalt(nazwa), a(a) {
		cout << "Tworze (obiekt) kwadrat " << nazwa << endl;
	}
	
	~Kwadrat() {
		cout << "Zegnaj (obiekt) kwadrat " << nazwa << endl;
	}

	virtual double pole() {
		return a*a;
	}
	
	virtual double obwod() {
		return a * 4;
	}
};


class Prostokat : public Kwadrat {
protected:
	double b;
public:
	Prostokat(double b, double a, string nazwa) : Kwadrat(a, nazwa), b(b) {
		cout << "Tworze (obiekt) prostokat " << nazwa << endl;
	}

	~Prostokat() {
		cout << "Zegnaj (obiekt) prostokat " << nazwa << endl;
	}

	virtual double pole() {
		return a * b;
	}

	virtual double obwod() {
		return (2 * a) + (2 * b);
	}
};

class Kolo : public Ksztalt {
protected:
	double r;
public:
	Kolo(double r, string nazwa) : Ksztalt(nazwa), r(r) {
		cout << "Tworze (obiekt) kolo " << nazwa << endl;
	}

	~Kolo() {
		cout << "Zegnaj (obiekt) kolo " << nazwa << endl;
	}

	virtual double pole() {
		return pi * pow(r, 2);
	}

	virtual double obwod() {
		return 2 * pi * r;
	}
};

class Trojkat : public Kolo {
protected:
	double h;
public:
	Trojkat(double h, double r, string nazwa) : Kolo(r, nazwa), h(h) {
		cout << "Tworze (obiekt) trojkat " << nazwa << endl;
	}

	~Trojkat() {
		cout << "Zegnaj (obiekt) trojkat " << nazwa << endl;
	}

	virtual double pole() {
		return 1 / 2 * r*h;
	}

	virtual double obwod() {
		return h*2;
	}
};

class BazaFigur {
protected:
	vector<Ksztalt*>kontenerfigur;
public:
	BazaFigur() {
	}
	~BazaFigur() {
		for (Ksztalt* k : kontenerfigur) {
			delete k;
		}
	}

	void dodajdokontenera(Ksztalt * k) {
		kontenerfigur.push_back(k);
		cout << "Dodalem " << (*k).getName() << endl;
	}

	//ostream& operator<<(ostream& o, BazaFigur const& b) {
	//	return b.pole(o);
	//}

	void wyswietlkontener(BazaFigur* b) {

		/*for (Ksztalt* s : kontenerfigur) {
			cout << s->getName() << " ma pole: " << s->pole() <<  " ma obwod: " << s->obwod() << endl;
		}*/

		vector<Ksztalt*>::iterator it;
		for (it=(b->kontenerfigur).begin(); it!=(b->kontenerfigur).end(); it++) {
			cout << *it << endl;
		}
	}

};
0

Udało mi się w końcu, dzięki za pomoc i motywacje bo już się miałem poddać :P

	void wyswietlkontener(BazaFigur* b) {

		/*for (Ksztalt* s : kontenerfigur) {
			cout << s->getName() << " ma pole: " << s->pole() <<  " ma obwod: " << s->obwod() << endl;
		}*/

		vector<Ksztalt*>::iterator it;
		for (it=(b->kontenerfigur).begin(); it!=(b->kontenerfigur).end(); it++) {
			cout << "P: " << (*it)->pole() << endl;
			cout << "O: " << (*it)->obwod() << endl;
		}
	}
3
Realmarecz napisał(a):
  1. No Kolo ma zmienną r koło trójkąt używa natomiast r i h. Mimo że są figurami różnymi no to nie widzę problemu żeby mogły dziedziczyć. Przykład z Kwadratem i Prostokątem jest typowym do nauki ze względu na dziedziczenie zmiennych, konstruktory, destruktory i metody - żeby zobaczyć o co chodzi z przesłanianiem, destruktorem virtual itp.

Nie są to przykłady typowe. Argument o używaniu zmiennych jest nietrafiony - dziedziczenie nie jest mechanizmem, który ma jedynie oszczędzić pisania kodu, tylko reprezentować logiczne zależności pomiędzy klasami.
Nawet jeśli to jest program edukacyjny - jaki sens ma mieszanie koła z trójkątem? Przedefiniowujesz wszystkie metody i dziedziczysz po kole tylko po to żeby uniknąć deklaracji jeszcze jednej zmiennej.

Parafrazując klasyka:

Realmarecz napisał(a):
  1. No czołg posiada koła, samolot natomiast używa kół i skrzydeł. Mimo że są pojazdami różnymi no to nie widzę problemu żeby mogły być budowane na podstawie tego samego schematu. Przykład z amfibią i pojazdem (który po amfibii dziedziczy) jest typowym do nauki ze względu na posiadanie podwozia, silnika, kół - żeby zobaczyć o co chodzi z jazdą nimi itp.
0

Akurat trójkąt i koło mogą mieć wiele wspólnego:

user image

Z innej strony:

Pojazd to akurat - coś jak kształt (pewnie chodziło ci o samochód/amfibia). W programach nie edukacyjnych pierw będę na kartce wykonywał projektowanie obiektowe - ale rozumiem o co ci chodzi z Trójkątem i Kołem i masz rację bo jak ktoś będzie szukał trójkątu to będzie szukał jako figury a nie jako pochodnej z koła.

0

Link nie działa. Poza tym programowanie obiektowe to nie matematyka i np. nie zawsze Kwadrat jest Prostokątem. Hierarchia dziedziczenia ma dbać o to, by obiekty zachowywały się poprawnie (zgodnie z oczekiwaniem), a nie na siłę odzwierciedlać własności matematyczne albo cechy świata rzeczywistego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1