Problem przy odczycie danych innej klasy

0

Witam forumowiczów i przychodzę do was z problemem (No shit Sherlock :P). Otóż napisałem sobie właśnie kod, dwie klasy, jedna dziedziczy drugą, jednak podczas używania :: i próby wczytania danych z klasy 1 pojawia się taki zapis matematyczny gdzie na końcu jest e+xx. Mógłby ktoś mi wyjaśnić co zrobiłem źle?

#include <iostream>
#include <cstdlib>
#include <math.h>

using namespace std;
class punkt
{
protected:
    float x, y;
    string nazwa;
public:
    void wczytaj()
    {
        cout << "Podaj wspolrzedna X: ";
        cin >> x;
        system("cls");
        cout << "Podaj wspolrzedna Y: ";
        cin >> y;
        system("cls");
        cout << "Podaj nazwe punktu: ";
        cin >> nazwa;
        system("cls");
    }
    void wypisz()
    {
        cout << "Punkt o wspolrzednych: (" << x << ";"<< y << ") nosi nazwe: " << nazwa << endl;
    }
};
class kolo
    :public punkt
{
    float r, P;
public:
    void wczytaj()
    {
        cout << "Podaj promien kola: ";
        cin >> r;
        system ("cls");
    }
    void wypisz()
    {
        cout << "Kolo posiada promien: " << r << " a srodek kola to punkt: " << punkt::nazwa << " o wspolrzednych: (" << punkt::x << ";" << punkt::y << ")" << endl;
    }
    void pole()
    {
        P = M_PI*r*r;
        cout << "Pole kola wynosi: " << P << endl;
    }
};

int main()
{
    punkt pkt;
    pkt.wczytaj();
    pkt.wypisz();

    kolo kolko;
    kolko.wczytaj();
    kolko.wypisz();
    kolko.pole();
    return 0;
}

0

Nigdy notacji naukowej nie widziałeś?
https://pl.wikipedia.org/wiki/Notacja_naukowa

0

Szweszwe wiem co to jest i na czym polega, jednak problemem jest to, że jak przy punkcie x=2 to czemu później przy wywołaniu punkt::x to się równa 2,089xxxxxe+033?
Nie pytałem o matematykę tylko o błąd w programie...

0

Przecież ten punkt który wczytujesz to jest jakiś obiekt punk. Nie ma nic wspólnego z obiektem kolo. Wypisujesz niezainicjalizowane wartości x i y z obiektu kolo i dostajesz głupoty.
W ogóle skąd pomysł, że koło powinno dziedziczyć z punkt?

0

Jeżeli chcesz użyć formatu bez notacji naukowej dodaj std::fixed do std::cout.
BTW - w klasie kolo zmienne x i y są niezainicjalizowane , stąd też wyświetlają się takie dziwne wartości.

0

Tu raczej nie chodzi o notacje :P
Tylko o to że tam jej nie powinno być.

Problem jest w main'ie.

int main()
{
    punkt pkt;   // obiekt punkt
    pkt.wczytaj();  // tutaj są ustawiane zmienne **nazwa, x , y**
    pkt.wypisz();

    kolo kolko;    // **inny** obiekt *kolko*, gdzie zmienne **nazwa, x , y** są nie ustawione
    kolko.wczytaj();
    kolko.wypisz();
    kolko.pole();
    return 0;
}

bazując na Twoim kodzie, to powinno zadziałać

int main()
{
    kolo *kolko = new kolo();
    punkt* pkt = dynamic_cast<punkt*>(kolko);
    pkt->wczytaj();
    pkt->wypisz();

    kolko->wczytaj();
    kolko->wypisz();
    kolko->pole();
    return 0;
}
0
R0ut4 napisał(a):

Mógłby ktoś mi wyjaśnić co zrobiłem źle?

Tak jak już powyżej zostało napisane - używasz zmiennych którym nie nadałeś żadnej wartości.
Poza tym, funkcja wczytaj i wypisz powinny być wirtualne a ich implementacja w klasie pochodnej powinna wywoływać implementacje z klasy rodzica

0

Pomyśl o użyciu podobnego wzorca:

using namespace std;

class Base
{

public:
   
    virtual void load()
    {
        cout << "Give x: "; cin >> x;
        cout << "Give y: "; cin >> y;
    }
    virtual void print( ostream& stream ) const
    {
        stream << "Base : x = " << x << " , y = "<< y << endl;
    }

protected:

    float x {0}, y {0};

};

ostream& operator<<( ostream& out , const Base& base )
{
    base.print( out );
    return out;
}

class Derived : public Base
{

public:

    void load() override
    {
        Base::load();
        cout << "Give z: "; cin >> z;
        Calculation = x+y+z;
    }
    void print( ostream& stream ) const override
    {
        Base::print( stream );
        stream << "Derived : z = " << z << " , Calculation = " << Calculation << endl;
    }

protected:

    float z {0}, Calculation {0};
};

int main()
{
    shared_ptr<Base> base = make_shared<Base>();
    base->load();
    cout << *base;

    shared_ptr<Base> derived = make_shared<Derived>();
    derived->load();
    cout << *derived;

    return 0;
}
4

Mnóstwo odpowiedzi, ale tylko @szweszwe zwrócił uwagę na coś, co dla początkującego programisty może być naprawdę przydatne (bo wybaczcie, ale przy tym poziomie zrozumienia jaki został zaprezentowany w pierwszym poście - opowiadanie o funkcjach wirtualnych nie ma najmniejszego sensu).

@R0ut4, BARDZO wielu nauczycieli (niestety - czasem również akademickich) przedstawia swoim uczniom dziedziczenie jako sposób na unikanie powielania kodu.
"Mamy klasę punkt, w tej klasie współrzędne, koło też ma współrzędne to znaczy że warto tu użyć dziedziczenia"
To jest złe podejście - dziedziczenie definiuje nam w programie bardzo ważną zależność między klasami.
Troszkę uproszczę, ale gdy rozpatrujesz związki między różnymi obiektami, to najczęściej spotkasz się z takimi sytuacjami

A USES B (A używa B)

Można powiedzieć, że to jeden z "najluźniejszych" związków. Obiekt B jest potrzebny obiektowi A do tego żeby wykonać jakąś konkretną akcję, ale poza tym nie są ze sobą w żaden sposób związane.
Przykładowo - masz klasę "Map", która oferuje "usługę" wyszukania najbliższego sklepu:

class Map
{
 ...
public:
  ... findShop(const Point &a) const;   // zastanów się, co ta funkcja może/powinna zwrócić ?
...
};

int main()
{
  Map m;
  Point p1 {51.4500616,16.217394};

  cout << m.findShop( p ) << endl;
}

Możemy powiedzieć, że mapa (obiekt m) UŻYWA punku (obiektu p) jako punktu orientacyjnego do znalezienia najbliższego sklepu.

A HAS_A B (A posiada B)

To już jest mocniejszy związek - mamy z nim do czynienia gdy jeden obiekt jest częścią składową drugiego obiektu.
Prosty przykład - Twój punkt POSIADA współrzędne x i y. Zamodelowałeś to dodając je jako pola klasy.

class Point {
  float x;
  float y;
...
};

Inne dość często spotykane przypadki - gdy jedna klasa posiada całą kolekcję obiektów jakiegoś typu - np. zebranie w którym uczestniczą pracownicy

class Employee { ... };

class Meeting {
  std::vector<Employee> participants; // częściej zamiast wartości przechowywalibyśmy tu jakiegoś rodzaju wskaźniki - ale to temat na przyszłość
...
};

A IS-A B (A jest szczególnym przypadkiem B)

Ten trzeci rodzaj zależności, to sytuacja w której mamy dwie klasy, w której jedna jest pewnym rozszerzeniem drugiej, ALE (co bardzo ważne) - nadal zachowuje jej wszystkie podstawowe właściwości.

Osoba i student.

Wyobraźmy sobie taki uproszczony model:
Osoba posiada imię i nazwisko. Każda osoba potrafi się przedstawić (podać swoje imię i nazwisko)
Student - posiada imię, nazwisko oraz dodatkowo numer indeksu.

Pytanie ?
Czy Osoba jest szczególnym przypadkiem Studenta ? (hmm, mamy tu odpowiednik githubowego spoiler tag-a ?)

Nie, bo nie każda osoba jest studentem. Nie każda osoba może być studentem - np. typowe dziecko w wieku 7 lat
posiada imię i nazwisko, potrafi się przedstawić - ale raczej nie zdało jeszcze matury i w związku z tym nie może być studentem

Czy Student jest szczególnym przypadkiem Osoby ?

Raczej tak...
Możemy powiedzieć, że KAŻDY student jest osobą (ale nie każda osoba jest studentem).

Jeśli mamy taką sytuację, to wtedy jest sens rozważać użycie dziedziczenia - (Student jako klasa pochodna od Osoby).

Pytanie - czy w Twoim przypadku można powiedzieć, że koło jest punktem ? Odpowiedź nie jest łatwa, bo zależy od tego co z tymi obiektami będziesz później robić...
Gdybyś np. w przyszłości chciał policzyć odległość między dwoma punktami

float distance ( const Point & p1, const Point & p2 )
{
 ...
}

to musiałbyś wziąć pod uwagę to, że ta funkcja powinna działać poprawnie również wtedy, gdy jako argument przekażemy jej Koło - bo dla kompilatora będzie to całkowicie legalne.
Definiując klasę koło jako klasę pochodną od punkt mówisz kompilatorowi, że każde koło jest punktem. Wszędzie tam gdzie wymagane jest dostarczenie punktu programista będzie
mógł użyć obiektu typu koło.

Inny przykład - co zrobisz, jeśli do programu będziesz musiał dodać klasę reprezentującą dowolny czworokąt. Jeśli chcesz w tym celu wykorzystac punkt - to w zasadzie czworokąt
jest kolekcją 4 punktów. Nie da się odziedziczyć kilka razy po tej samej klasie (*)... Można odziedziczyć punkt i dodać do klasy 3 kolejne - tylko jaki to ma sens ?

I teraz zaczynamy ewentualnie rozważac funkcje wirtualne i wgłębiać się w niuanse Liskov Substitution Principle ;)
Jeśli przetrawisz (ze zrozumieniem !) i będziesz miał ochotę na więcej to mogę rozszerzyć temat.

*)
tak, ja wiem ale nawet nie próbujcie mu tego teraz pokazywać ;)

0

Da się jakoś zamknąć wątek, czy to admin/mod muszą zrobić?

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