Konstruktor mówiący o rozmiarze tablicy

0

Witam,
Mam głupie pytanie i strasznie mnie drażni fakt, że nie potrafię zrobić tak banalnej rzeczy.
Muszę zrobić klasę która posiada m.in.:
– prywatny wskaźnik p na tablicę
– konstruktor z parametrem typu int, mówiący o rozmiarze tablicy alokowanej dynamicznej przez polecenie new

Mam coś takiego ale wydaje mi się to być błędne i nie wiem jak stworzyć tablicę o danym rozmiarze będącą obiektem tej klasy.

 
class Wektor
{
	float *p[];
public:
	Wektor(int);	
};
Wektor::Wektor(int a)
{
	
   *p=new float[a];	
}
0

tylko 2 błędy: po prostu tak:
p=new float[a];

float *p; //<-- w klasie tak

i uwaga: z tym, że implementując coś takiego nie zapomnij o konstruktorze kopiującym i operatorze przypisania (automatycznie wygenerują się metody, które kopiują wskaźnik zamiast całej tablicy, przez co mogą być problemy).

jeśli chcesz rzeczywiście pisać klasę tablicy może zastanów się czy nie lepiej użyć:
vector<typ> (#include <vector>)
ma on już wszystko co można chcieć od tablic

0

Prawie dobrze.
Usuń te [] z deklaracji p i usuń * przed p w konstruktorze.
Poczytaj o wskaźnikach i dynamicznej alokacji pamięci.

//edit: btw. float *p[]; to jest konstrukcja z C99 zero-sized array, w C++ dostępna jako rozszerzenie kompilatora(GCC i CLang to obsługują). Pozwala na stworzenie struktury o zmiennym rozmiarze, no i można to stosować tylko w klasie/strukturze/unii.

0

No ok, ale co ze stworzeniem obiektu takiej klasy w main.
Wektor *d=new Wektor(5);
czy tak? niby błędu nie wywala ale nie wiem jak operować na takiej tablicy,
Jak mogę dostać się do elementu z indeksem np. 3.

0

Jest kilka sposobów. Możesz napisać metody do tego służące, możesz przeładować operator[], możesz zmienić specyfikator dostępu dla p.
Z tego pytania wynika, że musisz jeszcze się dowiedzieć co to klasy i jak się z nich korzysta.

0

Hmm dalsza część zadania to:
– przeciążony operator >> jako funkcja/metoda klasy do wstawiania do tablicy liczb z klawiatury
– przeciążony operator << jako funkcja/metoda klasy do wyświetlania zawartości wektora na ekranie
z tym sobie raczej poradzę tylko nie mogę jakoś przegryźć tablicy tworzonej w ten sposób.
Czyli nie mogę się do niej dostać tak po prostu jak do zwykłej? Coś w stylu cout<<*d[3];
Chcę to zrobić żeby po prostu nauczyć się operować na tablicach tego typu.

0

Przecież klasa to nie tablica. Ta tablica, a raczej wskaźnik na nią jest częścią obiektów tej klasy.
Robiąc coś takiego potrzebny jest jeszcze destruktor, który zwolni pamięć.

0

już Ci pokazuje jak działa vector na przykładzie:

#include <vector>
using namespace std;

int main()
{
  vector<int> t; // tablica liczb całkowitych
  t.push_back(6); // dodaje na końcu tablicy liczbę 6
  t.resize(10,5); // zwiększa/zmniejsza rozmiar do 10, pola które były zostają nienaruszone, pozostałe (nowe) są wypełniane drugim parametrem (drugi parametr jest opcjonalny)
  int rozmiar = t.size();
  int liczba_na_pozycji_3 = t[3]; // w zasadzie jest to pozycja nr 4, bo elementy numerowane są od 0
  for (int i=0; i<t.size(); i++)
    {
      // operacja na t[i]
    }
  t.clear(); // czysci - czyszczenie nie musi oznaczac zwolnienia pamieci i najczesciej nie jest ona zwalniana - zwolnienie odbywa się dopiero jak vector jest zdjęty ze stosu (przy wywołaniu destruktora)
  return 0;
}

cały opis tu: http://www.cplusplus.com/reference/stl/vector/

jak chcesz stworzyć vector od razu z jakimś rozmiarem i wypełnionymi polami to:
vector<int> v(rozmiar, liczba); // liczba - wartosc ktora beda przyjmowac elementy

jak znasz rozmiar tablicy to najlepiej dodawać tak:
v.reserve(rozmiar); // nie zwiększa rozmiaru, ale klasa odpowiedzialna alokuje miejsce na te elementy dzięki czemu w trakcie dodawania elementow nie bedzie realokacji (w zasadzie ta realokacja to nie ejst zbytni problem bo z tego co wiem przy realokacji vector alokuje sobie dwukrotnie wiecej pamieci niz potrzebuje) - dla małych rozmiarów nie musisz tego robić

v.push_back(liczba); // dodajesz liczbę/y na koncu

0

Dzięki ale ja robię zadania na studia i muszę pisać dokładnie tak jak mam w poleceniu.
Zrobiłem takie metody ale pojawia mi się kolejne pytanie (nie denerwujcie się na mnie, po prostu chce się nauczyć).

 
#include <cstdlib>
#include <iostream>
using namespace std;

class Wektor
{public:
	float *p;
public:
	Wektor(int);
	void pokaz();	
	void wstaw();
};

Wektor::Wektor(int a)
{
	
   p=new float[a];	
}

void Wektor::wstaw()
{
	for(int i=0;i<7;i++)
	{
		cout<<"podaj liczby do tablicy";
		cin>>p[i];
	}
}

void Wektor::pokaz()
{
	for(int i=0;i<7;i++)
		cout<<p[i]<<endl;
}

////////////////////////////////////
//////////////////////////////////////
int main(int argc, char *argv[])
{
	Wektor *d=new Wektor(5);
	d->wstaw();
	d->pokaz();
	system("pause");
	return 0;
}

Wszystko działa tylko czemu mogę wychodzić poza zakres tablicy.
Chciałem ją ograniczyć na 6 elementów, a działa też dla większej ilości, czemu? Czyżby Wektor *d=new Wektor(5); ta 5 tutaj nie mówiła o rozmiarze?

0

W C++ nie ma czegoś takiego jak sprawdzanie czy przekraczasz zakres tablicy czy nie. To już do Ciebie należy pisać taki kod, żeby nie przekraczać zakresów tablic, bo to się może skończyć długimi poszukiwaniami powodu dziwnego zachowania aplikacji. Wychodząc poza zakres tablicy po prostu czytasz/piszesz po pamięci, która niekoniecznie należy do Ciebie, a jak należy do Ciebie to do innego obiektu i bóg wie co tam może być.

Do tej klasy Wektor dodaj pole przechowujące rozmiar tablicy, dzięki temu zawsze będziesz wiedział jak dużą tablicę masz.
Dodatkowo wypadałoby przechowywać indeks ostatnio wprowadzonego elementu, żeby wiedzieć gdzie wprowadzać następne i czy w ogóle. Przyda Ci się to przy pisaniu operatora >>.

Metoda wstaw powinna przyjmować jako argument wartość do wstawienia i wstawiać ją w ostatnie wolne miejsce, i/lub przyjmować dwa parametry: wartość jaką wstawić i pozycję na którą ją wstawić.

Metoda pokaż powinna raczej przyjmować jeden argument(indeks) i zwracać wartość siedzącą pod tym indeksem w tablicy. Wypisywanie powinieneś zrealizować operatorem <<.

0

Ja bym coś takiego zrobił (masz gotowca za starania :P)

#include <iostream>
#include <cstring>

using namespace std;

class Wektor
{
public:
  Wektor(int r): _rozmiar(r), p(new float[r]) {}
  Wektor(const Wektor& w): _rozmiar(w._rozmiar), p(new float[w._rozmiar])
    {
      memcpy(p,w.p,w._rozmiar*sizeof(float));
    }
  ~Wektor() { delete [] p; }
  int rozmiar() const { return _rozmiar; }
  float& operator[] (int index)
    {
      /*tutaj mozesz sobie dodatkowo sprawdzic czy ktos nie wychodzi poza zakres*/
      return p[index];
    }
  const float& operator[] (int index) const
    {
      /*tutaj mozesz sobie dodatkowo sprawdzic czy ktos nie wychodzi poza zakres*/
      return p[index];
    }
  void odwroc()
    {
      int h = _rozmiar/2;
      for (int i=0, r=_rozmiar-1; i<h; i++,r--)
        swap(p[i],p[r]);
    }
private:
  const int _rozmiar;
  float *p;
  
  // blokada przed przypisaniem nowego wektora
  const Wektor& operator= (const Wektor&) { return *this; }
};

ostream& operator<< (ostream& os, const Wektor& w)
{
  if (w.rozmiar()>0)
    os << w[0];
  for (int i=1; i<w.rozmiar(); i++)
    os << ", " << w[i];
  return os;
}

istream& operator>> (istream& is, Wektor& w)
{
  for (int i=0; i<w.rozmiar(); i++)
    {
      is >> w[i];
    }
  return is;
}

int main()
{
  int rozmiar;
  cout << "Podaj rozmiar: ";
  cin >> rozmiar;
  Wektor w(rozmiar);
  cout << "Podaj elementy tablicy:" << endl;
  cin >> w;
  cout << "Wpisales:\n" << w << endl;
  w.odwroc();
  cout << "W odwrotnej kolejnosci:\n" << w << endl;
  return 0;
}
1

Heh dzięki.
Gotowca nie wezmę bo wole się sam nauczyć ale na pewno do przeanalizowania się przyda i coś z tego w głowie mi zostanie :)

1

// blokada przed przypisaniem nowego wektora
const Wektor& operator= (const Wektor&) { return *this; }
ee.. ale dlaczego on ma ciało? powinien albo działać (i być publiczny), albo pusty:

  const Wektor& operator= (const Wektor&);

bo inaczej to kiedyś zapomnisz że jest on bzdurny.

1 użytkowników online, w tym zalogowanych: 0, gości: 1