2011-10-21 17 views
10

Mam pracę domową, która każe mi się wykonać następujące czynności:użyciu szablonów w C++

zaprojektować szablon klasy o nazwie FlexArray który oferuje elastycznym tablicę indeksów. Użytkownik klasy może ustawić niższy indeks i górny indeks po zadeklarowaniu obiektu.

Przykłady kodu użytkownika:

FlexArray a (1,5); // niższy indeks to 1, a górny indeks to 5 FlexArray b (-5, 10); // niższy wskaźnik wynosi -5 a górna indeksu jest 10

podać następujące funkcje dla swojej klasy:

  1. domyślny konstruktor
  2. parametryzowane konstruktor, w którym użytkownik określony indeks dolny i górny indeks
  3. destructor
  4. konstruktor kopii
  5. operatorowi przypisanie
  6. przeciążony [] operator z podobną semantyką do [] już używany z wbudowanymi tablicami.

Błędy w warunkach PRE mogą być obsługiwane za pomocą instrukcji assert lub bloków try/catch. Nie ma zmiany rozmiaru oferowanej macierzy. Indeksy dolne muszą znajdować się w zasięgu.

Książka naprawdę nie pomaga przy tworzeniu szablonów. Miałem nadzieję, że ktoś da mi wskazówki dotyczące tego problemu i sprawdzi, czy mój kod jest na dobrej drodze. Próbowałem uruchomić ten problem przez bardzo ograniczony zakres środków książek i różnych online i otrzymała:

#ifndef H_templates 
#define H_templates 

#include <iostream> 
using namespace std; 

template <typename T>   
class FlexArray 
{ public:     
    FlexArray();   // POST: empty FlexArray 
    FlexArray(LI,UI);    // POST: Parameterized Constructor 
    ~FlexArray();   // POST: destructor 
    CopyArr(Array* sourceArray, Array* destinationArray, size);    // POST: Copies array 

    //Overloading the assignment operators to add arrays(?) Unsure if 
    // this is what is meant by the original question 
    FlexArray operator+ 
     (const FlexArray& otherFlexArray) const; 
     //Overload the operator + 
    FlexArray operator- 
     (const FlexArray& otherFlexArray) const; 
     //Overload the operator - 
    FlexArray operator[] 
     (const FlexArray& otherFlexArray) const; 
     //Overload the operator [] 

private: 
    T FlexArray[size];  // Flex array 
    int size;    // number of items Array 
    int LI;     //Lower Index 
    int UI;     //Upper Index 
}; 

template <typename T> 
FlexArray<T>::FlexArray() 
// POST: empty FlexArray 
{ size = 0; } 

template <typename T> 
FlexArray<T>::~FlexArray() 
// POST: destructor 
{ } 
template <typename T> 
FlexArray<T>::CopyArr(Array* sourceArray, Array* destinationArray, size) 
//Pre: Takes 3 arguments, the original array, the array to copy too, and, the size of array 
// POST: Copies the array 
{ 
    for(int i=0; i<size; i++){ 
     sourceArray[i] = destinationArray[i] 
    } 
} 

#endif 
+1

Operator przypisania to 'operator ='. –

+2

+1 za zadanie domowe! – Marlon

+0

Szablon w C++ to rodzina obiektów - z tymi samymi funkcjami, ale hostująca inny obiekt. Na przykład użyj szablonów dla stosów, kolejek, list. NIE DLA RZECZY, KTÓRE MOGĄ "ZWIĄZEĆ Z NIĄ; (jak kształty/prostokąty/kwadraty/okręgi ...) –

Odpowiedz

6

Masz dobry start. Kilka rzeczy do wskazania.

Przypisanie prosi o domyślny konstruktor, ale stwierdza również, że zmiana rozmiaru tablicy nie jest obsługiwana. Te dwa wymagania logicznie kolidują - twoje założenie (do użycia size=0) wydaje się logiczne, ale wtedy ten domyślny skonstruowany obiekt będzie zawsze pusty. To nie jest duży problem, tylko logiczne rozłączenie w wymaganiach.

Konstruktor warstwowy, zajmujący górne i dolne krawędzie. Już rozpoczęła się to jako:

FlexArray(LI,UI);    // POST: Parameterized Constructor 

Jednak LI i UI trzeba typy. Ponieważ musisz obsługiwać ujemne indeksy, powinien to być typ podpisu, taki jak int.

Konstruktor kopii, jest konstruktorem, który przyjmuje obiekt tego samego typu. Nie zadeklarowałeś jednego z nich. Powinien on mieć postać:

FlexArray(const FlexArray&); 

Operator przypisania jest operator =, który pozwala, aby to zrobić:

FlexArray a, b; 
b = a; 

Nie zadeklarowali jednego z nich. Powinna ona przybrać formę:

FlexArray& operator=(const FlexArray&); 

Realizacja będą podobne do kopii konstruktora (w rzeczywistości, copy-konstruktor może po prostu być realizowane w warunkach operatora przypisania).

Przeciążony operator []. Zadeklarowałeś jedno z nich, ale tak naprawdę nie jest ono w poprawnej formie - nie przyjmuje odpowiednich typów argumentów. Użycie będzie wyglądać następująco:

FlexArray arr(-5, 10); 

// This is a call to operator[] 
arr[3] = value; 

Biorąc pod uwagę to, spróbuj pomyśleć o tym, jaki rodzaj argumentu powinien zająć.

Teraz, zgodnie z wymaganiami funkcjonalnymi. Biorąc pod uwagę górną i dolną granicę, musisz utworzyć tablicę, która może być indeksowana za pomocą tych granic. Zastanów się, co musisz wiedzieć, aby to zrobić. Zasugeruję, że musisz znać różnicę górnej i dolnej granicy (będzie to SIZE twojej tablicy).Powinieneś sprawdzić w konstruktorze, że górna granica jest większa niż dolna granica, lub nie możesz skutecznie utworzyć tej tablicy.

Teraz, aby faktycznie zbudować tablicę obiektów, trzeba dynamicznie przydzielić dla nich trochę pamięci. Spróbuj na tym z:

T FlexArray[size];  // Flex array 

Ale to ma pewne problemy. Po pierwsze, nie sądzę, żebyś mógł nazwać to FlexArray, ponieważ to zderzy się z nazwą twojej klasy. Po drugie, wymaga to, aby size była stałą czasową kompilacji, co jest niezgodne z naszymi wymaganiami. Będziesz więc musiał dynamicznie przydzielić wewnętrzną tablicę obiektów T (używając new, jeśli jeszcze nie nauczyłeś się o inteligentnych wskaźnikach). Pamiętaj, aby zwolnić tę tablicę obiektów w destruktorze.

Teraz funkcjonalnie, jak będzie działać []? Warunkiem jest sprawdzenie granic, więc biorąc pod uwagę indeks musisz wiedzieć, czy jest on zbyt niski (poza dolną granicą) lub zbyt wysoki (poza górną granicą) i podnieść odpowiedni błąd. Teraz masz przydzieloną dynamicznie (0-opartą) tablicę obiektów T - przy danym indeksie, który jest określony przez użytkownika, musisz znaleźć odpowiedni obiekt do zwrócenia. Zastanów się, jak to zrobić.

Użytkownik zadeklarował także operatorów + i -, chociaż wymóg ten nie określa, że ​​powinny tam być. Sugerowałbym je usunąć. Operator + sugeruje zmianę rozmiaru tablicy (co jest sprzeczne z wymaganiami), a - jest niejednoznaczny, co oznacza odjęcie dwóch tablic? Obie te funkcje mogą być poprawne, ale dla tego przypisania są niepotrzebne.

Brak dalszych wskazówek :)

+0

Dziękuję, że to bardzo pomocne. Dla konstruktora kopiowania, gdzie/jak faktycznie mogę napisać część do kopiowania dla szablonu? Wiem, że w poprzednich hw, gdy przeładowaliśmy coś, co napisaliśmy funkcję w jego własnym pliku .cpp, wydaje się, że wiele pozycji związanych z szablonami jest przechowywanych w pliku nagłówkowym lub może nawet nie mieć znaczenia. A więc: 'FlexArray :: operator = (const FlexArray &) const { \t \t \t // forloop, aby skopiować kod? \t} ' – Nick

+0

Tak, szablony mają cały kod w pliku nagłówkowym (ogólnie) i masz podstawową poprawną składnię. – Chad

+0

Również - zaktualizowana odpowiedź z jeszcze kilkoma innymi rzeczami ... – Chad

0

dobrze, pierwszą rzeczą, którą zauważysz przy bat jest to, że tak naprawdę nie ma kopii konstruktor. Jeśli myślisz, że kwalifikuje się CopyArr, to tak nie jest. Składnia powinna znajdować się w materiałach klasowych, ale w zasadzie jest to konstruktor, który przyjmuje odniesienie do klasy jako jedynego parametru.

Nie masz również operatora przypisania (aka: przypisanie kopii). Ponownie, dokładna składnia powinna znajdować się w materiałach klasowych, ale nazwa rutynowa to operator=.

Co więcej, operator twojej macierzy nie wydaje mi się mieć "podobnej semantyki do [] już używanej z wbudowanymi tablicami". Wbudowana tablica zwraca typ elementu (który byłby T w twoim przypadku, nie?), Ale twój zwraca cały typ FlexArray.

Jeśli chodzi o sam rozwój szablonu, oto co proponuję, jeśli masz problemy. Zacznij od opracowania całej rzeczy do pracy jako prosta (bez szablonu) klasa z jednym prostym typem (np .: int). Przetestuj i sprawdź, czy działa w ten sposób. Następnie przekształcić go w szablon. Śledzenie błędów w szablonach może stanowić wyzwanie nawet dla doświadczonych programistów.

+0

Konstruktor kopiujący * nie * po prostu przeładowuje operatora '='. Patrz http: //en.wik ipedia.org/wiki/Copy_constructor. To prawdziwy konstruktor. Jest on nazywany niejawnie, gdy przypisujesz instancję obiektu (uwaga: nie tylko wskaźnik, ale sam obiekt) lub gdy przekazujesz instancję obiektu do metody. –

+0

Och, próbowałem napisać funkcję kopiowania a przeciążać operatora '=' – Nick

+0

@JackEdmonds - Sorry. To był breif z mózgu. Naprawiono, zanim nawet zobaczyłem twój komentarz. Zdecydowanie warta -1, mimo że była tam. C++ jest wystarczająco mocny, aby się uczyć, nie myląc słabego OQ z niewłaściwą terminologią. –

0

Jak inne odpowiedzi nie poszły na to, istnieje kilka dziwnych rzeczy o:

template <typename T> 
FlexArray<T>::CopyArr(Array* sourceArray, Array* destinationArray, size) 
//Pre: Takes 3 arguments, the original array, the array to copy too, and, the size of array 
// POST: Copies the array 
{  
    for(int i=0; i<size; i++){ 
     sourceArray[i] = destinationArray[i] 
    } 
} 

Parametr size musiałby typ oraz nazwę.

Zrobiłeś z niego element obiektu, a mimo to nie działa on na tym obiekcie. Działa tylko na obiektach przekazanych w parametrach. Zamiast tego możesz ustawić tę funkcję jako jedną tablicę (tą, z której chcesz skopiować). Nazywają to assign. Następnie można go użyć do zaimplementowania swoich copy constructor i operator=.

Drugą osobliwością jest typ Array. Gdzie to jest zdefiniowane?

+0

Whoops :) nie jest nigdzie zdefiniowany. Patrzyłem na przykład w książce, czy mógłbym po prostu użyć 'CopyArr (sourceArray [], destinationArray [], size)'? – Nick

+0

W jakim kompilatorze uruchamiasz swój kod podczas pisania? (To jest załadowane pytanie!) –

+0

Używam MS Visual C++ 2010 do edycji i kompilacji. – Nick

0

Chcesz alokacji dynamicznej. Najprostszym sposobem na to jest użycie std::vector.

+0

Po prostu zaczęliśmy używać wektory w klasie na drugi dzień, więc wiem, że ma to znaczenie dla odrabiania zadań domowych. Czy mógłbyś nieco rozwinąć swoją odpowiedź. – Nick

+0

To jest dobra uwaga, ale możliwe, że zamiarem pytania jest przydzielenie pamięci z 'new' i' delete', ponieważ nie byłoby powodu, aby napisać własny konstruktor kopii, destruktor itp., Jeśli używasz 'std :: vector' dla twojego magazynu. Domyślne ustawienia zajmą wszystko dla Ciebie. –

+1

Nie jestem tego pewien, bo to była praca domowa. Byłoby całkiem możliwe zrobienie tego za pomocą tablicy i wygenerowanie wyjątku, jeśli użytkownik poprosi o zbyt daleko od siebie. Ale jeśli nauczyciel @ Nicka właśnie wprowadził wektory, może spytać nauczyciela o podpowiedź, czy powinien go tu użyć ... –

Powiązane problemy