Dlaczego przesuwa mi obydwie linie?

Dlaczego przesuwa mi obydwie linie?
T2
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:27
0
Kopiuj
#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;
} 
RE
Moderator
  • Rejestracja:około 18 lat
  • Ostatnio:12 miesięcy
2

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.

T2
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:27
0

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?

kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Łódź
  • Postów:1402
1

Stworzyć drugi element, zamiast przypisywać adres? Na przykład:

Kopiuj
 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!


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
T2
teraz program się zawiesza.
kaczus
Ponieważ używasz wskaźników, to musisz napisać odpowiedni konstruktor kopiujący. Sądziłem, że to jasne... Ogólnie zasada - jeśli nie umiesz operować na wskaźnikach, nie używaj ich zbyt często.
T2
tak właśnie myślałem, że co z konstruktorem kopiującym jest nie tak, lecz nie wiem co w nim zmienic.
T2
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:27
0

Konstruktor kopiujący zmieniłem na inny, ale nadal dwie linie się przesuwają:

Kopiuj
  Linia(const Linia * wzorzec)
    {
        *p1 = *(wzorzec->p1);
        *p2 = *(wzorzec->p2);
    }
kaczus
bo musisz miec kopie, ale nie adresów, tylko obiektów, a tu ogolnie masz krasz - bo przypisujesz w nieznane miejsce wartosci - ogólnie zarządzanie pamięcią jakie wymyśliłeś jest mało efektywne
T2
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:27
0

Dobra teraz działa:

Kopiuj
 Linia(const Linia & wzorzec)
    {
        this->p1 = new Punkt(*(wzorzec.p1));
        this->p2 = new Punkt(*(wzorzec.p2));
    }
edytowany 2x, ostatnio: tadzik287
kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Łódź
  • Postów:1402
1

Przypadkowo nawet ma szanse zadziałać prawidłowo... Ale sam projekt jest podatny na to by się wywalić, przy ździebko innym kodzie.


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
Zobacz pozostałe 11 komentarzy
T2
próbowałem pousuwać te wskaźniki i zrobić tak aby tylko w mainie tworzyć dynamiczne obiekty, ale się nie udało. Da się tak ?
kaczus
Ogólnie to powinno robić się odwrotnie - na zewnątrz jak najmniej obsługi rzeczy dynamicznych, a jeśli trzeba to w środku - tak należy projektować, żeby później nie dziwić się, czemu sie wiesza, skąd wycieki pamięci itd. Jeszcze jak unieszczęśliwisz siebie tak skopanym kodem, pół biedy - sam będziesz się męczył, gorzej, jak ktos po tobie przejmie ten kod....
T2
to ten kod jest aż tak bardzo zły ?
T2
mógłbyś pokazać jak powinien ten kod wyglądać w klasie Punkt i Linia ?
kaczus
Na początek pozbądź się wszelkich wskaźników w funkcjach udostępnianych na zewnątrz - jeśli zajdzie konieczność optymalizacji - zajmiesz się tym później.
T2
  • Rejestracja:ponad 9 lat
  • Ostatnio:ponad 9 lat
  • Postów:27
0

Bez wskaźników, tyle, że teraz nie mogę stworzyć obiektu dynamicznego linii, bo argumenty nie pasują do konstruktora.

Kopiuj
 #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;
}
kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Łódź
  • Postów:1402
0
Kopiuj
Linia *pierwsza = new Linia(*pierwszy, *drugi); 

Aczkolwiek dalej piszę, nie używaj wskaźników, jeśli nie umiesz....


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
Zobacz pozostały 1 komentarz
kaczus
A musisz tworzyć obiekt dynamiczny? - jeśli tak, to trudno - ale wtedy trzeba nauczyć się najpierw wskaźników.
T2
chyba aż takich tragicznych błędów z tymi wskaźnikami nie zrobiłem ?
kaczus
Jak napisałem - w oczy rzucało się kilka, a sam miales problemy, których nie rozumiałeś...
Endrju
Zrobiłeś tragiczne błędy. Nie zwolniłeś pamięci.
RE
Gorszy był ten, w którym używał niezainicjowanej pamięci :).
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
1

Zamień:

Kopiuj
  Punkt *pierwszy = new Punkt(1,1);

Na:

Kopiuj
  Punkt pierwszy(1,1);

Lub:

Kopiuj
  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:

Kopiuj
  auto pierwszy = make_shared<Punkt>(1,1);
RE
No i od C++14 mamy również make_unique, czyli jeszcze jeden powód mniej, żeby używać gołego new.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)