• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

C++ inne działania metody w konstruktorze i innej metodzie

Cloud VPS
0 głosów
597 wizyt
pytanie zadane 5 maja 2017 w C i C++ przez sofnir Gaduła (4,690 p.)

Witam, mam pewną klasę SimulationManager, która posiada tablicę wskaźników:

const CustomerType * customerType[3];

oraz mam pewną klasę CustomerFactory, która posiada wskaźnik na tablicę wskaźników:

const CustomerType ** customerType;

Klasa SimulationManagerPosiada obiekt klasy CustomerFactory, do którego na liście inicjalizacyjnej konstruktora podczas jego tworzenia przekazywana jest tablica wskaźników, aby w kontstruktorze CustomerFactory przypisać do niej wskaźnik. 

To tyle wstępu. Teraz meritum. Klasa CustomerFactory ma pewną metodę wyświetlającą pewne dane:

    for(int i = 0; i < 3; i++)
        std::cout << (*(customerType + i))->getVisitsCount() << std::endl;

Jeśli używam tej metody w konstruktorze klasy SimulationManager to otrzymuję prawidłowe wyniki, natomiast jeśli w jakiejś metodzie klasy SimulationManager to pierwsza wartość jest prawidłowa, druga to zawsze 1, a trzecia to już kompletne losowe głupoty.  Dodatkowo, jeśli w pętli zamiast i wstawię np. 0 czyli 3 razy wyświetlam tą samą wartość, to jest ona prawidłowa tylko za pierwszym razem, a potem 2 razy głupoty.

Nie mam pojęcia co może być nie tak, może macie jakieś wskazówki?

Pozdrawiam

2 odpowiedzi

0 głosów
odpowiedź 5 maja 2017 przez j23 Mędrzec (195,240 p.)
wybrane 5 maja 2017 przez sofnir
 
Najlepsza

(...) do którego na liście inicjalizacyjnej konstruktora podczas jego tworzenia przekazywana jest tablica wskaźników,

Pokaż, jak przekazujesz tę tablicę (chodzi o wywołanie konstruktora).

BTW, po co te zabawy z nawiasami, nie można tak:

std::cout << customerType[i]->getVisitsCount() << '\n';

?

komentarz 5 maja 2017 przez sofnir Gaduła (4,690 p.)

Tak można też po prostu wypisać customerType[i], a co do przekazywania tablicy:

SimulationManager::SimulationManager()
    :  customerFactory(customerType)

Konstruktor customerFactory:

CustomerFactory::CustomerFactory(const CustomerType ** customerType)
{
    this->customerType = customerType;
}
komentarz 5 maja 2017 przez j23 Mędrzec (195,240 p.)

Tu wszystko wygląda OK. Pewny jesteś, że wszystkie pola tablicy mają przypisane poprawne wskaźniki?

Unikaj nadawania tych samych nazw pól klasy i argumentów metod:

CustomerFactory::CustomerFactory(const CustomerType ** customerType_)
{
    customerType = customerType_;
}

 

komentarz 5 maja 2017 przez sofnir Gaduła (4,690 p.)

Tak jestem pewien. Może napiszę więcej kodu.

SimulationManager::SimulationManager()
    : shop(1, 2, 8, 9), customerFactory(customerType)
{
    unsigned openingPeriod = shop.getOpeningPeriod();

    JuniorType juniorType({0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10});
    AverageType averageType({0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10});
    SeniorType seniorType({0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10});

    customerType[JUNIOR] = & juniorType;
    customerType[AVERAGE] = & averageType;
    customerType[SENIOR] = & seniorType;

    for(int i = 0; i < CUSTOMERS_NUMBER; i++)
        customerType[i]->show();

    customerFactory.metoda(); //to jest ta moja metoda, tutaj działa poprawnie
    std::cout << std::endl;
}

void SimulationManager::simulation()
{
    customerFactory.randAverageTime(0);
}

Funkcja main:

SimulationManager simulationManager; //podczas tworzenia obiektu
 w konstruktorze urachamiana jest ta moja metoda i działa poprawnie
simulationManager.simulation(); //tutaj juz dziala tylko dla pierwszego elementu tablicy

Dlaczego w konstruktorze to działa, a poza nim już nie nie mam pojęcia, to nie powinno mieć znaczenia, przecież ja nie modyfikuje niczego tylko to wyświetlam.

komentarz 5 maja 2017 przez j23 Mędrzec (195,240 p.)

No i mamy winowajce:

JuniorType juniorType(...);
AverageType averageType(...);
SeniorType seniorType(...);
 
customerType[JUNIOR] = & juniorType;
customerType[AVERAGE] = & averageType;
customerType[SENIOR] = & seniorType;

Przypisujesz lokalne zmienne. Formalnie one przestają istnieć po opuszczeniu konstruktora.

 

komentarz 5 maja 2017 przez sofnir Gaduła (4,690 p.)
No tak racja... dzięki wielkie! Bardzo głupi błąd. Co byś polecił w zamian? Te obiekty JuniorType itd. zrobić jako prywatne elementy klasy SimulationManager, czy jest jakiś lepszy sposób?
komentarz 5 maja 2017 przez j23 Mędrzec (195,240 p.)

Najprościej to przerobić tak:

customerType[JUNIOR] = new JuniorType( {0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10} );
customerType[AVERAGE] = new AverageType( {0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10} );
customerType[SENIOR] = new SeniorType( {0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10} );

Później tą pamięć musisz w destruktorze usunąć.

Bardziej pr0 jest użyć inteligentnych wskaźników:

std::unique_ptr<CustomerType> customerType[3];

customerType[JUNIOR] = std::make_unique<JuniorType>( {0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10} );
customerType[AVERAGE] = std::make_unique<AverageType>( {0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10} );
customerType[SENIOR] = std::make_unique<SeniorType>( {0, 10}, {0, 10}, {0, 10}, {0, 10}, openingPeriod, {8, 10} );

Wtedy nie musisz nic usuwać, samo się usunie ;)

 

W obu przypadkach destruktor CustomerType powinien być wirtualny.

komentarz 5 maja 2017 przez sofnir Gaduła (4,690 p.)
To są te inteligentne wskaźniki, ale jeszcze do tego etapu w książce nie dotarłem za niecałe 100 stron będą to już będzie bardziej pro, na razie nie wiem z czym to się je :)
0 głosów
odpowiedź 5 maja 2017 przez MetGang Nałogowiec (34,360 p.)

Jeśli dobrze zrozumiałem to przesuwasz wskaźnik drugiego stopnia, a dopiero potem robisz dereferencję. W przypadku i == 0 odwołujesz się "prawidłowo" do pierwszego elementu tablicy, lecz potem przy i > 0 "uciekasz" wskaźnikiem drugiego stopnia od wskaźnika na tablicę.

Najpierw rób dereferencję ze wskaźnika drugiego stopnia, a potem dopiero poruszaj się po tablicy.

(*customerType)[i]

 

komentarz 5 maja 2017 przez j23 Mędrzec (195,240 p.)
edycja 5 maja 2017 przez j23

To, co napisałeś, będzie miało zastosowanie dla const CustomerType *** customerType; W obu przypadkach - wskaźnika i tablicy - dostęp do elementów jest taki sam, czyli customerType[i]-> ...

komentarz 5 maja 2017 przez sofnir Gaduła (4,690 p.)
edycja 5 maja 2017 przez sofnir
(*customerType)[i] nie zadziała, a faktycznie można po prostu zastosować customerType[i], ale to i tak nic nie zmienia

Podobne pytania

0 głosów
2 odpowiedzi 1,370 wizyt
0 głosów
2 odpowiedzi 4,397 wizyt
pytanie zadane 14 listopada 2016 w C i C++ przez xjakubekx Obywatel (1,280 p.)
0 głosów
2 odpowiedzi 356 wizyt

93,486 zapytań

142,418 odpowiedzi

322,771 komentarzy

62,899 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...