Kłopot przy przeladowaniu operatora "-" przy uzyciu f. globalnej zaprzyjaznionej z klasą.

0

Cześć wszystkim!

Mam problem z tym kodem:

#include <iostream>

using namespace std;

////////////////////////////////////////////////////////////////////////////////////////////////////////////
//a)Konstruktor inicjujący wartości x, y, z,
//b)Konstruktor kopjujący
//c)Funkcje składową dodająca dwa wektory w następujący (x1+x2, y1+y2, z1+z2)

class Wektor {
private:
    float *x, *y, *z;

public:
    inline void wyswietl(void)
    {
        cout << "X: " << *x << endl
             << "Y: " << *y << endl
             << "Z: " << *z << endl;
    }

    Wektor(float a = 0, float b = 0, float c = 0) /* LINE 98 */
    {

        x = new float(a);
        y = new float(b);
        z = new float(c);
    }
    Wektor(Wektor& source) /*  LINE 104  */
    {

        x = source.x;
        y = source.y;
        z = source.z;
    }
    Wektor operator+(const Wektor& pWektor)
    {

        Wektor tmp;

        *tmp.x = *this->x + *pWektor.x;
        *tmp.y = *this->y + *pWektor.y;
        *tmp.z = *this->z + *pWektor.z;

        return tmp;
    }

    friend Wektor operator-(const Wektor& lWektor, const Wektor& pWektor);
};

Wektor operator-(const Wektor& lWektor, const Wektor& pWektor1)
{
    /* Wektor a;
 
    *a.x = *lWektor.x - *pWektor1.x;
    *a.y = *lWektor.y - *pWektor1.y;
    *a.z = *lWektor.z - *pWektor1.z;
 
    return a;
  */
    return Wektor(*lWektor.x - *pWektor1.x, *lWektor.y - *pWektor1.y, *lWektor.z - *pWektor1.z); /*   LINE 138   to nie chce zadziałać  */
}

int main()
{

    Wektor O(1, 2, 3);
    Wektor P(1, 10, 1);
    Wektor C;

    C = O + P;
    Wektor A(C);

    C.wyswietl();
    cout << "----------------\n\n\n";
    A.wyswietl();

    C = P - O;
    C.wyswietl();
    return 0;
} 

konsola Code:

 ||=== Build: Debug in nauka_C_przeladowanie (compiler: GNU GCC Compiler) ===|
||In function 'Wektor operator-(const Wektor&, const Wektor&)':|
|138|error: no matching function for call to 'Wektor::Wektor(Wektor)'|
|138|note: candidates are:|
|104|note: Wektor::Wektor(Wektor&)|
|104|note:   no known conversion for argument 1 from 'Wektor' to 'Wektor&'|
|98|note: Wektor::Wektor(float, float, float)|
|98|note:   no known conversion for argument 1 from 'Wektor' to 'float'|

||=== Build failed: 1 error(s), 1 warning(s) (0 minute(s), 0 second(s)) ===|

IDEA: Odjąć dwa wektory i zwrócić wynik do 3 wektora.

Chodzi o funkcję globalną operator- , nie kompiluje się kod gdy chcę zwrócić returnem obiekt stworzony przez konstruktor jawnie wywołany. Dla zmiennej pomocniczej wew. f. śmiga.

P.S. Pragnę dodać że dopiero się uczę, na innych stronach widziałem że takie rozwiązanie przez k. jawny działa. Nie wiem czy ma to coś wspólnego z wskaźnikiem this?
Link do stronki z której korzystałem: http://edu.pjwstk.edu.pl/wyklady/pro/scb/PRG2CPP_files/node120.html

Pozdrawiam!

2
  1. Zapoznaj się z pojęciem formatowania kodu: http://4programmers.net/Forum/998482
  2. Zapoznaj się z operatorem -> oraz czym się różni od operatora .. Właśnie brak pojmowania tego stoi ci na przeszkodzie.
2

U mnie się kompiluje, ale:

  1. Dlaczego nikt nie odpowiada w moim wątku?
  2. dlaczego dynamicznie alokujesz x, y i z? (a jak już, dlaczego nie używasz unique_ptr?)
  3. dlaczego kopiujesz wskaźniki w konstruktorze kopiującym?
  4. masz wyciek pamięci (brak delete - ogółem używanie nagich new i delete jest prawie zawsze błędem)
  5. masz fatalne formatowanie kodu (polecam http://format.krzaq.cc )
  6. wyswietl nie powinno być częścią składową klasy Wektor (SRP)
  7. używanie nieangielskich nazw zmiennych nie jest dobrym pomysłem ( http://4programmers.net/Forum/1208091 )
  8. operatory + i - powinny być realizowane w oparciu o operatory += i -=
0

Generalnie to jest tylko przykład na którym sobie ćwiczę.

  1. Przyswoję :).
  2. Alokuje dynamicznie bo muszę powiedzieć kompilatorowi na jaki adres mają wskazywać te wskaźniki a potem pod tymi adresami są wartości dopinane w nawiasie(inaczej musiałbym chyba jakieś sztuczne zmienne stworzyć i pod te wskaźniki ich adresy wpisać. Nie wiem czy dobrze rozumiem ;/.
  3. No myślałem że w ten sposób nowe obiekty będą mieć wskaźniki ustawione na ten sam adres co obiekt źródłowy dostarczony do konstruktora kopiującego, żeby móc poustawiać je w nowym obiekcie.
  4. Wiem że powinienem użyć np. destruktora i tam zastosować delete ale chciałem na szybko sprawdzić moje rozumienie przeładowań i klepania kodu dla nich.
  5. Doceniam konstruktywną uwagę.
  6. Dlaczego? Wiem że nie musiałem dawać specyfikatora inline bo on domyślnie tam jest jeśli funkcję zadefiniuję w klasie.
  7. Dzięki za radę.
  8. Dlaczego? Chciałem tak o, dla wgl zaznajomienia się z tematem. Przeładować operator "-".

Nie za bardzo rozumiem.

Zapoznaj się z operatorem -> oraz czym się różni od operatora .. Właśnie brak pojmowania tego stoi ci na przeszkodzie.

Ale gdzie to będzie miało miejsce?

Ten cały kod który udostępniłem skompiluje się ale gdy użyję return Wektor(*lWektor.x - *pWektor1.x, *lWektor.y - *pWektor1.y, *lWektor.z - *pWektor1.z); do wyprowadzenia wyniku z tej funkcji to Code::Blocks krzyczy.

Wektor operator-(const Wektor& lWektor,const Wektor& pWektor1){
    Wektor a;
 
    *a.x = *lWektor.x - *pWektor1.x;
    *a.y = *lWektor.y - *pWektor1.y;
    *a.z = *lWektor.z - *pWektor1.z;
 
 
return a;
 
//return Wektor(*lWektor.x - *pWektor1.x, *lWektor.y - *pWektor1.y, *lWektor.z - *pWektor1.z);
//     nie dziala jak wstawie tutaj konstruktor jawny w return
2

2-4) Jaki konkretnie jest zysk z dynamicznej alokacji x, y i z? Z jakiego powodu nie użyjesz ich jako zwykłych członków klasy? float x,y,z ⟵ cały problem alokacji i dealokacji rozwiązany, nie wspominając już o zysku wydajnościowym.

  1. co ma do tego inline? SRP: https://en.wikipedia.org/wiki/Single_responsibility_principle klasa Wektor nie powinna implementować wyświetlania. Ona ma implementować wektor.

  2. DRY oraz aby zagwarantować taką samą implementację, a jeśli chodzi o kierunek to implementacja -= w oparciu o - będzie używała zbędnych zmiennych tymczasowych. Nie jest to dla początkującego aż takie ważne, raczej ciekawostka/warto wiedzieć.

2

Ad 2. Ma być: class Wektor { private: double x,y,z; ...
Ad 3. Po czym zmieniasz wartość x dla jednego z obiektów a zmienia się x w obu, WTF?
Ad 6. Ponieważ nie da się tej metody użyć w innym projekcie.
Ad 7. Aby a+=b dawało ten sam wynik co a=a+b niezależnie od zmian w kodzie. Owszem da się na odwrót operator += zrobić za pomocą + ale będzie nadmiarowy kod.

0
  1. Z tą alokacją to dlatego bo chciałem poćwiczyć także tutaj wskaźniki, wiem że bez nich jest lepiej w tym wypadku..
  2. Wyświetlanie to najmniejszy problem tutaj, ta klasa mogła się nazywać ciasteczko123, ten przykład z "wektorem" jest od tak dla picu. Te wskaźniki też dla picu bo chce je tylko poćwiczyć w "dziwnych przypadkach". Nie mniej jednak popatrzę o co chodzi z tym SRP.
  3. Okej to jeszcze poczytam o tym jak będę bardziej "rozkokszony" w programowaniu.
2

Ad 1. To nadaj wektorowi nazwę - poćwiczysz wskaźniki, napisy, kopiowanie itp
Ad 2. Będziesz ćwiczyć na złych przykładach - wejdzie to w krew.

0

Ad 3. Po czym zmieniasz wartość x dla jednego z obiektów a zmienia się x w obu, WTF?

Mógłbyś przybliżyć? Bo nie za bardzo rozumiem. Hmm chodzi o to że ten x zmienia się zarówno w obiekcie źródłowym i tym który chce stworzyć jako kopię tego pierwszego? No nie powinno tak być..
To będzie tak?:

    Wektor(Wektor& source) /*  LINE 104  */
    {
 
        *x = *source.x;
        *y = *source.y;
        *z = *source.z;
    } 
2

Tak jak podałeś - brak przydzielenia pamięci dla x,y,z - powinno się wywrócić z Access Violation

0
_13th_Dragon napisał(a):

Tak jak podałeś - brak przydzielenia pamięci dla x,y,z - powinno się wywrócić z Access Violation

Kurczę muszę się temu bliżej przyjrzeć, wychodzi na to, że w tym kopiującym konstruktorze też muszę dynamicznie przydzielić pamięć bo tak jak mówisz zmienna nowa nie dostanie adresu(dobrze rozumiem?). Na dziś sobie daruję. Wrócę do tego pewnie jutro.

Serdecznie dziękuje Wam za odpowiedzi i trafne uwagi.

2

Tak jest. Wcześniej kopiowałeś adres, wobec czego dwie instancje Wektor wskazywały na te same dane, przez co zmiana jednej była widoczna w drugiej. Teraz kopiujesz wartości, ale w nowym wektorze te wskaźniki nie wskazują na nic konkretnego, więc masz UB - mażesz po "losowych" miejscach w pamięci.

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