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

dynamiczna tablica obiektów, stos

Ostatnio zmodyfikowano 2017-04-23 12:53
Autor Wiadomość
andrzejek97
Temat założony przez niniejszego użytkownika
dynamiczna tablica obiektów, stos
» 2017-04-22 17:55:58
Wita, mam problem z napisaniem programu, który ma implementować stos oparty o tablicę, otóż w zadaniu miałem stworzyć interfejs Stack zawierający wirtualne metody void push(Item* obj), void pop() oraz Item* get(), odpowiadające za: umieszczanie elementu na stosie, usunięcie elementu ze stosu oraz zwrócenie aktualnego elementu, klasę Item zawierającą pole name typu string i jednoargumentowy konstruktor tego samego typu, oraz klasę ArrayStack implementującą stos oparty o tablicę (tu mam problemy), klasa ta ma dziedziczyć po interfejsie Stack, jej konstruktor ma przyjmować argument typu int opisujący maksymalny rozmiar stosu. Czy dobrze rozumiem, że ta tablica ma być tablicą obiektów typu Item, jeśli tak to dlaczego takie przydzielenie pamięci nie działa, wiem, że jeśli dopiszę w klasie Item konstruktor domyślny to zadziała, lecz czy to jest odpowiednie rozwiązanie problemu, wklejam kod, w komentarz dałem metody push, pop i get, mam nadzieję, że zadziałają po rozwiązaniu problemu z przydzieleniem pamięci, a może źle zrozumiałem treść zadania, proszę o odpowiedź.
C/C++
#include<iostream>

using namespace std;
class Item;
class Stack
{
public:
    virtual void push( Item * obj ) = 0;
    virtual void pop() = 0;
    virtual Item * get() = 0;
};

class Item
{
    string name;
public:
    Item( string _name )
        : name( _name )
    { }
};
class ArrayStack
    : public Stack
{
    int top;
    Item * tablicaStos;
public:
    ArrayStack( int rozmiar )
    {
        tablicaStos = new Item( "nazwa" )[ rozmiar ];
        top = - 1;
    }
    virtual void push( Item * obj )
    {
        // tablicaStos[++top]=obj;
    } //ummieszczenie elementu na stosie
    virtual void pop()
    {
        //delete tablicaStos[top--];
    } //usuniecie elementu ze stosu
    virtual Item * get()
    {
        //return tablicaStos[top];
    } //zwrocenie aktualnego elementu
};
int main()
{
    return 0;
}
P-160363
j23
» 2017-04-22 18:14:42
dlaczego takie przydzielenie pamięci nie działa, wiem, że jeśli dopiszę w klasie Item konstruktor domyślny to zadziała, lecz czy to jest odpowiednie rozwiązanie problemu
Nie działa, bo nie ma takiej konstrukcji new[], żeby tworzyć tablice obiektów wywołując konstruktory parametryczne. Musisz dodać konstruktor domyślny.

Inna opcja to użyć placement new:

C/C++
int rozmiar;
...

ArrayStack( int n )
    : rozmiar( n )
{
    tablicaStos =( Item * ) new char[ n * sizeof( Item ) ];
    top = - 1;
}

~ArrayStack()
{
    delete[]( char * ) tablicaStos;
}


...

void push( Item * obj )
{
    int i = top + 1;
    if( i == rozmiar ) throw std::out_of_range( "overflow!" );
   
    new(( char * ) & tablicaStos[( top = i ) ] ) Item( * obj );
}

void pop()
{
    if( top < 0 ) throw std::out_of_range( "underflow!" );
   
    tablicaStos[ top-- ].~Item();
}
Choć i tu musisz dodać konstruktor kopiujący.
P-160365
andrzejek97
Temat założony przez niniejszego użytkownika
» 2017-04-22 18:57:42
bardzo dziękuję ,a czy takie rozwiązanie przejdzie, wolałbym ominąć dodawanie konstruktora kopiującego
C/C++
#include<iostream>

using namespace std;
class Item;
class Stack
{
public:
    virtual void push( Item * obj ) = 0;
    virtual void pop() = 0;
    virtual Item * get() = 0;
};

class Item
{
    string name;
public:
    Item( string _name )
        : name( _name )
    { }
    Item() { }
};
class ArrayStack
    : public Stack
{
    int top;
    Item * tablicaStos;
public:
    ArrayStack( int rozmiar )
    {
        tablicaStos = new Item[ rozmiar ];
        top = - 1;
    }
    virtual void push( Item * obj )
    {
        tablicaStos[ ++top ] = * obj;
    } //ummieszczenie elementu na stosie
    virtual void pop()
    {
        tablicaStos[ top-- ];
    } //usuniecie elementu ze stosu
    virtual Item * get()
    {
        return & tablicaStos[ top ];
    } //zwrocenie aktualnego elementu
};
P-160368
j23
» 2017-04-22 19:08:22
Po dodaniu konstruktora domyślnego przejdzie. tylko push i pop powinny sprawdzać, czy nie przekraczają zakresu tablicy (patrz mój przykład).

push według mnie powinna przyjmować const referencję zamiast tego wskaźnika.


PS. wcześniej popieprzyło mi się z tym konstruktorem kopiującym. Nie musisz go definiować przy takiej konstrukcji klasy Item.
P-160369
j23
» 2017-04-22 20:16:18
Jeszcze jedna rzecz: dodaj destruktor, który zwalnia pamięć tablicaStos.


Tu jeszcze poprawiony destruktor z mojego przykładu:
C/C++
~ArrayStack()
{
    for( int i = 0; i <= top; ++i ) tablicaStos[ i ].~Item();
   
    delete[]( char * ) tablicaStos;
}
P-160371
andrzejek97
Temat założony przez niniejszego użytkownika
» 2017-04-22 21:02:06
Dziękuję, w poleceniu jest, że push ma przyjmować wskaźnik, więc tego zmienić nie mogę, get też później zwraca wskaźnik
C/C++
virtual Item * get()
{
    return & tablicaStos[ top ];
}
P-160374
andrzejek97
Temat założony przez niniejszego użytkownika
» 2017-04-23 12:53:03
P-160402
« 1 »
  Strona 1 z 1