2011-12-22 21 views
5

próbuję wdrożyć dynamiczną tablicę:tablicy dwuwymiarowej przy użyciu szablonów

template <typename Item> 
class Array { 
private: 
    Item *_array; 
    int _size; 
public: 
    Array(); 
    Array(int size); 
    Item& operator[](int index); 
}; 

template <typename Item> 
Array<Item>::Array() { 
    Array(5); 
} 

template <typename Item> 
Array<Item>::Array(int size) { 
    _size = size; 
    _array = new Item [size]; 

    for (int i = 0; i < size; i++) 
     cout << i << " " << _array[i] << " " << &_array[i] << endl; 
} 

template <class Item> 
Item& Array<Item>::operator[](int index) { 
    if (index < 0 || index > _size-1) 
     cout << "this: " << this << ". Index out of range" << endl; 

    return _array[index]; 
} 

Przy zastosowaniu tak, to działa zgodnie z oczekiwaniami, czyli druki 5:

Array<int> testArray(5); 
testArray[0] = 5; 
cout << testArray[0] << endl; 

Jednak chciałbym lubię używać klasy do dwuwymiarowej tablicy dynamicznej. Pomyślałem, że następujące po prostu magicznie działają i drukują 5 ...

Array< Array<int> > testArray(5); 
testArray[0][0] = 5; 
cout << testArray[0][0] << endl; 

... ale to nie działa. Zawiesza się, gdy próbuję ustawić wartość na [0] [0]. Debugger pokazuje mi, że this ma _size ustawiony na 0 i _array na NULL. this w tym miejscu wskazuje na pierwszy element _array ostatniej utworzonej instancji macierzy.

Jedną z rzeczy, których nie otrzymuję, jest to, że "wewnętrzna" tablica wywołuje swojego konstruktora. Przechodząc przez kod, widzę, że Array(int size) jest wywoływany raz i Array() pięć razy. Chciałbym utworzyć wewnętrzną tablicę o określonym rozmiarze, ale przy użyciu Array< Array<int>(10) > testArray(5) nie kompiluje.

Czy możesz dać mi wgląd w to? Wygląda na to, że nie mogłem jeszcze nakręcić głowy szablonami ...

Odpowiedz

6

Nie można łączyć wywołań konstruktorów w C++. Twoja pierwsza implementacja konstruktora nic nie robi, więc 5 instancji zawartych w rodzicu Array zostaje niezainicjowanych, co powoduje niezdefiniowane zachowanie.

Aby naprawić, można dodać wartość domyślną do parametru size innego konstruktora lub oddzielić logikę inicjalizacji w oddzielnej (prywatnej) funkcji i wywołać ją z obu konstruktorów.

EDIT: Powodem pierwszy konstruktor nie robi nic, jest to, że linia

Array(5) 

nie wywołać konstruktor bieżącej instancji, lecz przydziela nowy (nienazwany) czasowe Array instancję, która jest natychmiast niszczone na końcu linii.

+0

Och, nie wiedziałem, że nie można połączyć połączeń z konstruktorami! Teraz utworzyłem prywatną funkcję i teraz działa, ale tylko z rozmiarem określonym w domyślnym konstruktorze. Wszelkie pomysły na tworzenie wewnętrznej tablicy o rozmiarze dynamicznym? – fabian789

+0

Jeśli używasz C++ 11 ** i ** zewnętrzny rozmiar tablicy jest statycznie znany, możesz użyć listy inicjalizatora, aby zapewnić inicjatory dla wszystkich wewnętrznych tablic. W każdym razie, zapomniałem napisać to w mojej odpowiedzi, ale jeśli nie jest to nic innego niż ćwiczenie, prawdziwym rozwiązaniem jest użycie 'std :: vector'. –

+0

Tak, to tylko ćwiczenie. Czy możesz mi powiedzieć, co masz na myśli z "listą inicjalizującą"? używanie '_array = new Item [size] (size);' nie kompiluje się dla mnie. – fabian789

1

Nie można wywołać innego ctor od domyślnego ctor. Jeśli chcesz mieć wartość domyślną, możesz połączyć te dwa w jeden.

template <typename Item> 
Array<Item>::Array(int size = 5) { 
    _size = size; 
    _array = new Item [size]; 

    for (int i = 0; i < size; i++) 
     cout << i << " " << _array[i] << " " << &_array[i] << endl; 
} 

Jednak jeśli nadal wolą mieć dwa konstruktor następnie można przenieść do prywatnej implementacji funkcji _setup które mogą być używane zarówno w ten sposób.

template <typename Item> 
Array<Item>::Array() { 
    _setup(5); 
} 

template <typename Item> 
Array<Item>::Array(int size) { 
    _setup(size); 
} 

template <typename Item> 
void Array<Item>::_setup(int size) { 
    _size = size; 
    _array = new Item [size]; 

    for (int i = 0; i < size; i++) 
     cout << i << " " << _array[i] << " " << &_array[i] << endl; 
} 

niego usunięte nieprawidłową inicjatora do newed tablicy.

+0

Dodawanie (rozmiar) po nawiasach [] nie kompiluje się dla mnie ...? – fabian789

+0

Więc wydaje się, że wyprzedziłem siebie i zapomniałem, że nie możesz określić inicjalizatora dla tablic z nowym oświadczeniem. Być może użycie wektora zamiast wskaźnika do tablicy byłoby idealne. Podejrzewam, że jeśli dla klasy i nie można użyć żadnego istniejącego stl. – jbreiding

+0

Tak, to tylko ćwiczenie :) – fabian789

Powiązane problemy