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: #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 ]; } 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 ) { delete[] m_pnTablica; m_uRozmiar = aTablica.Rozmiar(); m_pnTablica = new TYP[ m_uRozmiar ]; for( unsigned i = 0; i < m_uRozmiar; ++i ) m_pnTablica[ i ] = aTablica[ i ]; 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; }
template < typename TYP > class TArray < TArray < TYP > > { static const unsigned DOMYSLNY_ROZMIAR = 5; private: TYP * m_pTablica; unsigned m_uRozmiarX; unsigned m_uRozmiarY; public: 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; } unsigned RozmiarX() const { return m_uRozmiarX; } unsigned RozmiarY() const { return m_uRozmiarY; } 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 []? |
|
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. |
|
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. |
|
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. |
|
DejaVu |
» 2013-08-09 15:50:34 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:
std::vector < std::vector < int > > v;
std::cout << v[ 0 ][ 0 ];
i działa. Napiszesz:
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). |
|
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ę: TArray < TYP >& operator []( unsigned uIndex );
/EDIT A ponieważ powyższe wymaga zmiany reprezentacji, to może lepiej spróbować TYP * operator []( unsigned uIndex );
|
|
Bimbol Temat założony przez niniejszego użytkownika |
» 2013-08-09 16:06:27 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:
std::vector < std::vector < int > > v;
std::cout << v[ 0 ][ 0 ];
i działa. Napiszesz:
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ę:
TArray < TYP >& operator []( unsigned uIndex );
/EDIT A ponieważ powyższe wymaga zmiany reprezentacji, to może lepiej spróbować
TYP * operator []( unsigned uIndex );
|
Spróbuję. |
|
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. |
|
« 1 » 2 3 |