#include <iostream>
#include<vector>
using namespace std;
class Punkt
{
int x, y;
public:
Punkt()
{
this->x = 0;
this->y = 0;
}
Punkt(int xx, int yy)
{
this->x = xx;
this->y = yy;
}
Punkt(const Punkt & wzorzec)
{
this->x = wzorzec.x;
this->y = wzorzec.y;
}
void przesun(int dx, int dy)
{
x += dx;
y += dy;
}
friend ostream & operator<<(ostream & ekran, Punkt & p);
};
ostream & operator<<(ostream & ekran, Punkt & p)
{
ekran << "(" <<p.x << ",";
ekran << p.y << ") " << endl;
return ekran;
}
class Linia
{
Punkt *p1, *p2;
public:
Linia() : p1(new Punkt()), p2(new Punkt(2,2))
{
}
Linia(Punkt *pierwszy, Punkt *drugi) : p1(pierwszy), p2(drugi)
{
}
Linia(const Linia & wzorzec)
{
*p1 = *(wzorzec.p1);
*p2 = *(wzorzec.p2);
}
void przesun(int dx, int dy)
{
p1->przesun(dx,dy);
p2->przesun(dx,dy);
}
void wypisz()
{
cout << "Linia:" << endl;
cout << "Punkt pierwszy: ";
(operator<<(cout,*p1));
cout << "Punkt drugi: ";
(operator<<(cout,*p2)) << endl;
}
~Linia()
{
delete p1;
delete p2;
}
};
int main()
{
Punkt *pierwszy = new Punkt(1,1);
cout << *pierwszy;
Punkt *drugi = new Punkt(2,2);
cout << *drugi;
Linia *pierwsza = new Linia(pierwszy,drugi);
Linia *druga = pierwsza;
pierwsza->przesun(2,2);
pierwsza->wypisz();
druga->wypisz();
return 0;
}
Linia *druga = pierwsza;
Dlatego. Zadziałało tutaj kopiowanie, ale nie twojego obiektu, a wskaźnika. Używasz ich zdecydowanie zbyt dużo, ten program nie powinien zawierać ani jednego! Jest w nim ponadto kilka błędów - użycie niezainicjowanej pamięci, wycieki.
Program miał się składać z samych obiektów dynamicznych, dlatego tyle wskaźników. Jakie błędy mam i jak prawidłowo wykonać kopiowanie aby nie przesuneło 2 linii?
Stworzyć drugi element, zamiast przypisywać adres? Na przykład:
Linia *druga = new Linia(*pierwsza);
oczywiście MUSISZ dodać zwalnianie pamięci i naucz sie tego juz teraz, żeby ktoś później po Tobie nie musiał sprzątać wycieków pamięci!
Konstruktor kopiujący zmieniłem na inny, ale nadal dwie linie się przesuwają:
Linia(const Linia * wzorzec)
{
*p1 = *(wzorzec->p1);
*p2 = *(wzorzec->p2);
}
Dobra teraz działa:
Linia(const Linia & wzorzec)
{
this->p1 = new Punkt(*(wzorzec.p1));
this->p2 = new Punkt(*(wzorzec.p2));
}
Przypadkowo nawet ma szanse zadziałać prawidłowo... Ale sam projekt jest podatny na to by się wywalić, przy ździebko innym kodzie.
Bez wskaźników, tyle, że teraz nie mogę stworzyć obiektu dynamicznego linii, bo argumenty nie pasują do konstruktora.
#include <iostream>
#include<vector>
using namespace std;
class Punkt
{
int x, y;
public:
Punkt()
{
this->x = 0;
this->y = 0;
}
Punkt(int xx, int yy)
{
this->x = xx;
this->y = yy;
}
Punkt(const Punkt & wzorzec)
{
this->x = wzorzec.x;
this->y = wzorzec.y;
}
void przesun(int dx, int dy)
{
x += dx;
y += dy;
}
friend ostream & operator<<(ostream & ekran, Punkt & p);
};
ostream & operator<<(ostream & ekran, Punkt & p)
{
ekran << "(" <<p.x << ",";
ekran << p.y << ") " << endl;
return ekran;
}
class Linia
{
Punkt p1, p2;
public:
Linia() : p1(Punkt()), p2(Punkt(2,2))
{
}
Linia(Punkt & pierwszy, Punkt & drugi) : p1(pierwszy), p2(drugi)
{
}
Linia(const Linia & wzorzec)
{
this->p1 = Punkt(wzorzec.p1);
this->p2 = Punkt(wzorzec.p2);
}
void przesun(int dx, int dy)
{
p1.przesun(dx,dy);
p2.przesun(dx,dy);
}
void wypisz()
{
cout << "Punkt pierwszy: ";
(operator<<(cout,p1));
cout << "Punkt drugi: ";
(operator<<(cout,p2)) << endl;
}
};
int main()
{
Punkt *pierwszy = new Punkt(1,1);
Punkt *drugi = new Punkt(2,2);
Punkt *trzeci = new Punkt(3,3);
Punkt *czwarty = new Punkt(8,8);
Punkt *piaty = new Punkt(10,10);
Linia *pierwsza = new Linia(pierwszy,drugi);
Linia *druga = new Linia(drugi,trzeci);
Linia *trzecia = new Linia(trzeci,czwarty);
Linia *czwarta = new Linia(czwarty,piaty);
delete pierwszy,drugi;
return 0;
}
Linia *pierwsza = new Linia(*pierwszy, *drugi);
Aczkolwiek dalej piszę, nie używaj wskaźników, jeśli nie umiesz....
Zamień:
Punkt *pierwszy = new Punkt(1,1);
Na:
Punkt pierwszy(1,1);
Lub:
Punkt pierwszy = {1,1};
Jeśli chcesz używać wskaźników:
- każdy "new" pakujesz do smart pointera lub kasujesz przez delete
- stosuj smart pointery (taka wersja pośrednia między alokacją dynamiczną a na stosie)
Przykład dla smart pointera:
auto pierwszy = make_shared<Punkt>(1,1);