Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Dynamiczna alokacja a konstruktory. (Pomoc w zadaniu)

Ostatnio zmodyfikowano 2021-05-04 23:22
Autor Wiadomość
deBe.
Temat założony przez niniejszego użytkownika
Dynamiczna alokacja a konstruktory. (Pomoc w zadaniu)
» 2021-05-04 22:06:20
Aplikacja się kompiluje, brak błędów w logu, jednak nie działa poprawnie. Opis zadania prezentuje się następująco: Napisz funkcję main() wczytującą liczbę wieloboków, N, a następnie liczby wierzchołków kolejnych wieloboków. Program powinien utworzyć tablicę N obiektów typu Wielobok a następnie posortować ją rosnąco ze względu na obwód wielokąta i wypisać.
Niestety nie mogę znaleźć błędu w kodzie więc wstawiam całość.
C/C++
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <cmath>
using namespace std;
class Point
{
   
int x;
   
int y;
   
public:
   
Point();
   
void print() const;
   
double dist( const Point & );
   
friend void print_point( const Point & );
};
class Wielobok
{
   
int n;
   
Point * vertices;
   
public:
   
Wielobok() { };
   
Wielobok( int );
   
Wielobok( const Wielobok & );
   
~Wielobok();
   
void print() const;
   
double circum();
};
void print_point( const Point & P ) {
   
cout << "(" << P.x << ", " << P.y << ") ";
}
int main()
{
   
srand( time( NULL ) );
   
int n, ile;
   
cout << "Podaj liczbe wielobokow: "; cin >> n;
   
Wielobok * polygons = new Wielobok[ n ];
   
cout << "Podawaj liczbe wierzcholkow kolejnych wielobokow";
   
for( int i = 0; i < n; i++ ) {
       
cout << "\nWielobok " << i + 1 << ": "; cin >> ile;
       
Wielobok X( ile );
       
polygons[ i ] = X
    }
   
bool guard = true;
   
while( guard ) { ///sortowanie
       
guard = false;
       
//for(int i = 0; i < n - 1; i++)
       
for( int j = 0; j < n - 1; j++ )
       
{
           
if( polygons[ j ].circum() > polygons[ j + 1 ].circum() ) {
               
swap( polygons[ j ], polygons[ j + 1 ] );
               
guard = true;
           
}
        }
    }
///wypisanie posortowanych
   
int k = 0;
   
cout << "\nPosortowane wieloboki wg obwodu: \n";
   
while( k < n ) {
       
cout << k + 1 << ". --> "; polygons[ k ].print(); cout << "\n";
       
k++;
   
}
   
delete[ ] polygons;
   
return 0;
}
//Point::Point() : x{rand()%21 - 10}, y{rand()%21 - 10} {cout << "Point(): "; print();}
Point::Point()
{
   
this->x = rand() % 21 - 10;
   
this->y = rand() % 21 - 10;
   
//cout << "Point(): "; print();
}
void Point::print() const
{
   
printf( "(%i, %i)", x, y );
}
double Point::dist( const Point & P )
{
   
return sqrt( pow( P.y - y, 2 ) + pow( P.x - x, 2 ) );
}
Wielobok::Wielobok( int n )
{
   
this->n = n;
   
this->vertices = new Point[ n ];
   
for( int i = 0; i < n; i++ ) {
       
Point x;
       
vertices[ i ] = x;
   
}
   
cout << "Wielobok(): "; // print();
}
Wielobok::Wielobok( const Wielobok & wb )
{
   
this->n = wb.n;
   
this->vertices = new Point[ n ];
   
for( int i = 0; i < n; i++ ) {
       
Point x;
       
vertices[ i ] = x;
   
}
   
cout << "(Copy ctor)--> Wielobok(): "; print();
}
Wielobok::~Wielobok()
{
   
cout << "~Wielobok(): "; // print();
   
delete[ ] vertices;
}
void Wielobok::print() const
{
   
cout << n << "-kat o wierzcholkach: ";
   
for( int i = 0; i < n; i++ ) print_point( vertices[ i ] );
   
}
double Wielobok::circum()
{
   
double circ = 0;
   
for( int i = 0; i < n - 1; i++ ) {
       
circ += vertices[ i ].dist( vertices[ i + 1 ] );
       
if( i == n - 2 ) circ += vertices[ n - 1 ].dist( vertices[ 0 ] );
       
   
}
   
return circ;
}
Tak wygląda konsola:
Podaj liczbe wielobokow: 3
Podawaj liczbe wierzcholkow kolejnych wielobokow
Wielobok 1: 3
Wielobok(): ~Wielobok():
Wielobok 2: 4
Wielobok(): ~Wielobok():
Wielobok 3: 5
Wielobok(): ~Wielobok():
Posortowane wieloboki wg obwodu:
1. --> 3-kat o wierzcholkach: (10683768, 10686056) (-2, -8) (4, 3)
2. --> 4-kat o wierzcholkach: (10724160, 10687328) (-3, -10) (-4, 6) (6, 10)
3. --> 5-kat o wierzcholkach: (10724160, 10687328) (-3, -10) (-4, 6) (6, 10) (4, -5)
~Wielobok(): ~Wielobok(): ~Wielobok():
Process returned 0 (0x0)   execution time : 5.434 s
Press any key to continue.
Po dłuższej analizie wydaje mi się że znalazłem winowajce. Mianowicie jest to ten kawałek kodu:
C/C++
int n, ile;
cout << "Podaj liczbe wielobokow: "; cin >> n;
Wielobok * polygons = new Wielobok[ n ];
cout << "Podawaj liczbe wierzcholkow kolejnych wielobokow";
for( int i = 0; i < n; i++ ) {
   
cout << "\nWielobok " << i + 1 << ": "; cin >> ile;
   
Wielobok X( ile );
   
polygons[ i ] = X;
}
Zamieniając go w ten sposób:
C/C++
int n, ile;
cout << "Podaj liczbe wielobokow: "; cin >> n;
Wielobok * polygons = new Wielobok[ n ];
cout << "Podawaj liczbe wierzcholkow kolejnych wielobokow";
for( int i = 0; i < n; i++ ) {
   
cout << "\nWielobok " << i + 1 << ": "; cin >> ile;
   
Wielobok X( ile );
   
polygons[ i ] = X;
   
polygons[ i ].print();
}
for( int i = 0; i < n; i++ ) { cout << endl; polygons[ i ].print(); }
W konsoli wygląda to następująco:
Podaj liczbe wielobokow: 3
Podawaj liczbe wierzcholkow kolejnych wielobokow
Wielobok 1: 3
Wielobok(): 3-kat o wierzcholkach: (-1, -4) (0, 8) (2, -6) ~Wielobok():
Wielobok 2: 4
Wielobok(): 4-kat o wierzcholkach: (9, -2) (0, 1) (-5, -4) (3, -9) ~Wielobok():
Wielobok 3: 5
Wielobok(): 5-kat o wierzcholkach: (0, 4) (2, -6) (-8, -4) (-10, 5) (-8, -5) ~Wielobok():
3-kat o wierzcholkach: (14222712, 14225000) (0, 8) (2, -6)
4-kat o wierzcholkach: (14263104, 14226272) (2, -6) (-8, -4) (-10, 5)
5-kat o wierzcholkach: (14263104, 14226272) (2, -6) (-8, -4) (-10, 5) (-8, -5)
Posortowane wieloboki wg obwodu:
1. --> 3-kat o wierzcholkach: (14222712, 14225000) (0, 8) (2, -6)
2. --> 4-kat o wierzcholkach: (14263104, 14226272) (2, -6) (-8, -4) (-10, 5)
3. --> 5-kat o wierzcholkach: (14263104, 14226272) (2, -6) (-8, -4) (-10, 5) (-8, -5)
~Wielobok(): ~Wielobok(): ~Wielobok():
Process returned 0 (0x0)   execution time : 1.408 s
Press any key to continue.
Wierzchołki wieloboków wyświetlają się poprawnie w pętli, jednak po wyjściu z niej wartości zostały zmienione.
P-178537
pekfos
» 2021-05-04 22:18:22
C/C++
polygons[ i ] = X;
Dla tego zapisu musisz zaimplementować operator przypisania. Konstruktor kopiujący jest używany przy tworzeniu obiektu jako kopii, a nie przy kopiowaniu wartości do istniejącego wcześniej obiektu.
P-178538
deBe.
Temat założony przez niniejszego użytkownika
» 2021-05-04 22:24:24
Jaki "istniejący wcześniej obiekt" masz na myśli? W sensie
polygons[ i ]
? Myślałem, że pisząc
Wielobok * polygons = new Wielobok[ n ];
 jedynie alokuje pamięć o wielkości sizeof(Wielobok) * n. Czyli wraz z alokacją nastąpiła inicjalizacja domyślnym konstruktorem bezargumentowym?
P-178539
DejaVu
» 2021-05-04 22:25:28
Ten zapis alokuje tablicę obiektów typu Wielobok. Tak, nastąpiła inicjalizacja wszystkich obiektów konstruktorem domyślnym (bezargumentowym jak to nazwałeś), ale później robisz przypisanie.

/edit:
C/C++
Wielobok * polygons = new Wielobok[ n ]; //tu się wywołują konstruktory domyślne
cout << "Podawaj liczbe wierzcholkow kolejnych wielobokow";
for( int i = 0; i < n; i++ ) {
   
cout << "\nWielobok " << i + 1 << ": "; cin >> ile;
   
Wielobok X( ile ); // tu się wywoła konstruktor z argumentem typu 'int'
   
polygons[ i ] = X; // tu się wywoła operator przypisania (którego nie masz, więc wykona się domyślna implementacja, która zachowuje się niezgodnie z Twoim oczekiwaniem)
   
polygons[ i ].print(); // tu wywołujesz metodę print().
}
P-178540
pekfos
» 2021-05-04 22:28:21
Czyli wraz z alokacją nastąpiła inicjalizacja domyślnym konstruktorem bezargumentowym?
Tak. Dodatkowo ten konstruktor niczego u Ciebie nie robi, pewnie został dorzucony tylko żeby kod się kompilował. W efekcie masz teraz tablicę obiektów z niezainicjalizowanymi wskaźnikami w środku. To trzeba poprawić, żeby przypisanie potem działało poprawnie.
P-178541
deBe.
Temat założony przez niniejszego użytkownika
» 2021-05-04 22:30:22
Czyli po zapisie
Wielobok * polygons = new Wielobok[ n ];
 w tej tablicy, którą reprezentuje wskaźnik polygons, znajdują już się obiekty typu Wielobok bez zainicjalizowanych wartości pól? Jest możliwość jedynie deklaracji tablicy o n elementach typu Wielobok bez inicjalizacji?
P-178542
pekfos
» 2021-05-04 22:33:16
Da się, ale wtedy musisz też ręcznie niszczyć obiekty (dodatkowo do ręcznego zwalniania pamięci). Najlepiej nie robić tego samemu i użyć do tego celu std::vector<> i metod emplace() / emplace_back().
C/C++
std::vector < Klasa > tablica;
tablica.emplace_back( argumenty, konstruktora );
P-178543
DejaVu
» 2021-05-04 22:33:24
C/C++
Wielobok * * polygons = new Wielobok *[ n ];
Wówczas uzyskasz tablicę wskaźników, ale... czy warto iść w tym kierunku? Może warto wówczas zrobić:
C/C++
std::vector < std::shared_ptr < Wielobok >> polygons;

//...

auto x = std::make_shared < Wielobok >( ile );
x->print();
polygons.push_back( x );
P-178544
« 1 » 2
  Strona 1 z 2 Następna strona