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

Szablon klasy, dla tablicy wielowymiarowej

Ostatnio zmodyfikowano 2013-08-10 02:02
Autor Wiadomość
Bimbol
Temat założony przez niniejszego użytkownika
Szablon klasy, dla tablicy wielowymiarowej
» 2013-08-08 23:39:08
Witam, natrafiłem na dosyć kłopotliwą sytuację.

Mianowicie, polecenie zadania brzmi:
(Bardzo trudne) Dodaj do specjalizacji TArray<TArray<TYP> > przeciążony operator [], który będzie działał w ten sam sposób, jak dla zwykłych wielowymiarowych tablic języka C++. Wskazówka: operator ten będzie wobec tablicy używany dwukrotnie. Pomyśl więc, jaką wartość (obiekt tymczasowy) powinno zwracać jego pierwsze użycie, aby drugie zwróciło w wyniku żądany element tablicy.

Kod:
C/C++
#include <iostream>
#include <memory.h>

using namespace std;

template < typename TYP > class TArray
{
    static const unsigned DOMYSLNY_ROZMIAR = 5;
protected:
    TYP * m_pnTablica;
    unsigned m_uRozmiar;
public:
    explicit TArray( unsigned uRozmiar = DOMYSLNY_ROZMIAR )
        : m_uRozmiar( uRozmiar )
        , m_pnTablica( new TYP[ uRozmiar ] )
    { }
    TArray( const TArray & );
   
    ~TArray() { delete[] m_pnTablica; }
    TYP Pobierz( unsigned uIndeks ) const
    {
        if( uIndeks < m_uRozmiar )
             return m_pnTablica[ uIndeks ];
        else
             return 0;
       
    }
    bool Ustaw( unsigned uIndeks, TYP nWartosc )
    {
        if( uIndeks >= m_uRozmiar ) return false;
       
        m_pnTablica[ uIndeks ] = nWartosc;
        return true;
    }
    unsigned Rozmiar() const { return m_uRozmiar; }
    TYP & operator []( unsigned uIndeks ) { return m_pnTablica[ uIndeks ]; }
   
    // Szablon metody
    template < typename U >
    TArray < TYP >& operator =( TArray < U >& );
};

template < typename TYP >
TArray < TYP >::TArray( const TArray & aTablica )
{
    m_uRozmiar = aTablica.m_uRozmiar;
    m_pnTablica = new TYP[ m_uRozmiar ];
    memcpy( m_pnTablica, aTablica.m_pnTablica, m_uRozmiar * sizeof( TYP ) );
}

template < typename TYP >
template < typename U >
TArray < TYP >& TArray < TYP >::operator =( TArray < U >& aTablica )
{
    // niszczymy w³asn¹ tablicê
    delete[] m_pnTablica;
    // tworzymy now¹, o odpowiednim rozmiarze
    m_uRozmiar = aTablica.Rozmiar();
    m_pnTablica = new TYP[ m_uRozmiar ];
    // przepisujemy zawartoœæ tablicy przy pomocy pêtli
    for( unsigned i = 0; i < m_uRozmiar; ++i )
         m_pnTablica[ i ] = aTablica[ i ];
    // zwracamy referencjê do w³asnego obiektu
    return * this;
}

template < typename TYP > class TDynamicArray
    : public TArray < TYP >
{
public:
    bool ZmienRozmiar( unsigned );
};

template < typename TYP > bool TDynamicArray < TYP >::ZmienRozmiar( unsigned uNowyRozmiar )
{
    if( !( uNowyRozmiar > this->m_uRozmiar ) ) return false;
   
    TYP * pNowaTablica = new TYP[ uNowyRozmiar ];
    memcpy( pNowaTablica, this->m_pnTablica, this->m_uRozmiar * sizeof( TYP ) );
    delete[] this->m_pnTablica;
    this->m_pnTablica = pNowaTablica;
    this->m_uRozmiar = uNowyRozmiar;
    return true;
}

/* Specyfikacja wielowymiarowej */

template < typename TYP > class TArray < TArray < TYP > >
{
    static const unsigned DOMYSLNY_ROZMIAR = 5;
private:
    // wskaźnik na tablicę
    TYP * m_pTablica;
    // wymiary tablicy
    unsigned m_uRozmiarX;
    unsigned m_uRozmiarY;
   
public:
    // konstruktor i destruktor
    explicit TArray( unsigned uRozmiarX = DOMYSLNY_ROZMIAR, unsigned uRozmiarY = DOMYSLNY_ROZMIAR )
        : m_uRozmiarX( uRozmiarX )
        , m_uRozmiarY( uRozmiarY )
        , m_pTablica( new TYP[ uRozmiarX * uRozmiarY ] )
    { }
   
    ~TArray() { delete[] m_pTablica; }
   
    //-------------------------------------------------------------
    // metody zwracające wymiary tablicy
    unsigned RozmiarX() const { return m_uRozmiarX; }
    unsigned RozmiarY() const { return m_uRozmiarY; }
   
    //-------------------------------------------------------------
    //operator () do wybierania elementów tablicy
    TYP & operator ()( unsigned uX, unsigned uY ) { return m_pTablica[ uY * m_uRozmiarX + uX ]; }
    TYP & operator []( unsigned uIndex )
    {
        static TYP uIndexY = uIndex;
        return uIndex;
    }
};

int main()
{
    cout << "Hello world!" << endl;
    TArray < TArray < int > > Array( 1, 1 );
    cout << Array( 0, 0 ) << endl;
    cout << Array[ 1 ][ 1 ] << endl;
    return 0;
}

Problem w tym, że kod się nawet nie kompiluje, bo i niby czemu skoro to jest dwuwymiarowa tablica, działająca jako jedno wymiarowa.
Więc jak można tutaj zastosować dwa operatory []?
P-89754
DejaVu
» 2013-08-09 14:42:58
1. Podaj błędy kompilacji.
2. Szablonowe typy danych często trzeba poprzedzać słowem kluczowym
typename
 deklaracjach/definicjach metod.
P-89792
DejaVu
» 2013-08-09 14:44:36
przeciążony operator [], który będzie działał w ten sam sposób, jak dla zwykłych wielowymiarowych tablic języka C++.
Nie da się przeciążyć operatora [] tak, aby miał coś wspólnego z wielowymiarowymi tablicami. Da się co najwyżej obsługiwać wywołania tak jak dla tablicy jednowymiarowej.

/edit:
Tak swoją drogą ten kod woła o pomstę do nieba - nie wiem co Ciebie zainspirowało do używania słowa kluczowego static wewnątrz operatora [], ale to jest z definicji złe.
P-89794
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-08-09 15:27:32
przeciążony operator [], który będzie działał w ten sam sposób, jak dla zwykłych wielowymiarowych tablic języka C++.


Nie da się przeciążyć operatora [] tak, aby miał coś wspólnego z wielowymiarowymi tablicami. Da się co najwyżej obsługiwać wywołania tak jak dla tablicy jednowymiarowej.

No właśnie, więc to zadanie jest bez sensu.



/edit:

Tak swoją drogą ten kod woła o pomstę do nieba - nie wiem co Ciebie zainspirowało do używania słowa kluczowego static wewnątrz operatora [], ale to jest z definicji złe.

Szczerze zainspirowało mnie to:
Wskazówka: operator ten będzie wobec tablicy używany dwukrotnie. Pomyśl więc, jaką wartość (obiekt tymczasowy) powinno zwracać jego pierwsze użycie, aby drugie zwróciło w wyniku żądany element tablicy.

Czyli wychodzi na to, że moje kombinowanie było złe i nie potrzebne.
P-89805
DejaVu
» 2013-08-09 15:50:34
C/C++
template < typename TYP >
class TArray
{
public:
    TYP & operator []( unsigned uIndeks ) { return m_pnTablica[ uIndeks ]; }
};
To jest wystarczający typ.

Zobacz sobie np. na std::vector. Napiszesz:
C/C++
std::vector < std::vector < int > > v;
//...
std::cout << v[ 0 ][ 0 ];
i działa. Napiszesz:
C/C++
TArray < TArray < int > > v;
//...
std::cout << v[ 0 ][ 0 ];
i również działa (bo pierwszy operator[] zwraca referencję na obiekt TAray<int>, a drugi operator zwraca referencję na int).
P-89807
Monika90
» 2013-08-09 15:53:13
Twój kod jest bardzo nieczytelny ze względu na te dziwne prefiksy, ale jeżeli dobrze rozumiem co chesz osiągnąć za pomocą jawnej specjalizacji TArray, to operator [] powinien mieć taką deklarację:
C/C++
TArray < TYP >& operator []( unsigned uIndex );

/EDIT
A ponieważ powyższe wymaga zmiany reprezentacji, to może lepiej spróbować
C/C++
TYP * operator []( unsigned uIndex );

P-89808
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-08-09 16:06:27
C/C++
template < typename TYP >
class TArray
{
public:
    TYP & operator []( unsigned uIndeks ) { return m_pnTablica[ uIndeks ]; }
};

To jest wystarczający typ.



Zobacz sobie np. na std::vector. Napiszesz:

C/C++
std::vector < std::vector < int > > v;
//...
std::cout << v[ 0 ][ 0 ];

i działa. Napiszesz:

C/C++
TArray < TArray < int > > v;
//...
std::cout << v[ 0 ][ 0 ];

i również działa (bo pierwszy operator[] zwraca referencję na obiekt TAray<int>, a drugi operator zwraca referencję na int).

Vektora jeszcze nie przerabiałem, a o drugiej sytuacji wiem. Jednak to jest zadanie i trzymałem się treści.
Specjalizacje szablonu TArray<TArray<TYP> > pisał autor kursu.


Twój kod jest bardzo nieczytelny ze względu na te dziwne prefiksy, ale jeżeli dobrze rozumiem co chesz osiągnąć za pomocą jawnej specjalizacji TArray, to operator [] powinien mieć taką deklarację:
C/C++
TArray < TYP >& operator []( unsigned uIndex );

/EDIT
A ponieważ powyższe wymaga zmiany reprezentacji, to może lepiej spróbować
C/C++
TYP * operator []( unsigned uIndex );


Spróbuję.
P-89809
Monika90
» 2013-08-09 16:08:58
@DejaVu
To jest wystarczający typ.
Powinien być wystarczający ale nie jest, bo nie da się skonstruować tablicy, której drugi wymiar byłby różny od 5.
P-89810
« 1 » 2 3
  Strona 1 z 3 Następna strona