inicjalizacja konstruktora przy tworzeniu tablicy new'em

0

Mam taki problem, probuje za pomoca new stworzyc tablice klas i przy okazji musze wywolac konstrkutor dla kazdej z tych klas. No właśnie i jak to zrobic??



/* Metoda alokujaca pamiec mojej klasy w ktorej tworze tablice klas wiersz 
 *  m,n zmienne prywarne klasy macierz -> jej rozmiary
*/
void 
macierz::alokuj() { 
  t = new wiersz[m](n);
  
  /* A teraz zerujemy macierz */
  for(int y=0;y<m;y++) 
    for(int x=0;x<n;x++) {
      t[y][x] = 0;
    }
  cout << "konstruktor";
}

/* konstruktor klasy wiersz */
wiersz::wiersz(int _rozmiar) {
    rozmiar = _rozmiar;
    w = new TYP[rozmiar];
}

Kompilator na ten kod reaguje tak :

g++ -c macierz.cpp
macierz.cpp: In member function ‘void macierz::alokuj()’:
macierz.cpp:61: error: ISO C++ forbids initialization in array new
make: *** [macierz.o] Błąd 1
0
#include <new>
//...
   wiersz* t = (wiersz*) calloc(m, sizeof(wiersz));
   for(int i=0;i<n;i++) new(&t[i]) wiersz(n); 
//...
   //czyszczenie pamieci
   for(int i=0;y<n;i++) t[i].~wiersz();
   free(t); //czyscimy pamiec

Ale to nie jest zbyt eleganckie rozwiązanie. Lepiej byłoby użyć konstruktora domyślnego (normalne new) i w pętli zmienić rozmiar każdego wiersza na 'n'.

To cię powinno zainteresować:

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

template<class T>
class macierz
{
private:
   class wiersz_base
   {
   public:
      vector<T> dane;
      wiersz_base(int rozmiar) { dane.resize(rozmiar, 0); };
      wiersz_base& operator=(const wiersz_base& kopia) { dane = kopia.dane; return *this; };
   };
public:
   class wiersz : protected wiersz_base
   {
   public:
      T& operator[](int index) { return dane[index]; };
      const T& operator[](int index) const { return dane[index]; };
   }; 
private:
   int n;
   vector<wiersz_base> wiersze;
public:
   macierz() { n = 0; }
   macierz(int _m, int _n): n(_n) { wiersze.resize(_m, wiersz_base(_n)); }
   macierz(const macierz& kopia) { *this = kopia; };
   int wysokosc() const { return wiersze.size(); };
   int szerokosc() const { return n; };
   wiersz& operator[](int index) { return reinterpret_cast<wiersz&>(wiersze[index]); };
   const wiersz& operator[](int index) const { return reinterpret_cast<const wiersz&>(wiersze[index]); };
   macierz& operator=(const macierz& kopia) { n = kopia.n; wiersze = kopia.wiersze; return *this; };
   friend ostream& operator<<(ostream& ostr, const macierz& M)
   {
      for(int i = 0; i < M.wysokosc(); i++)
      {
         for(int j = 0; j < M.szerokosc(); j++)
            ostr << M[i][j] << ' ';
         ostr << endl;
      }
      return ostr;
   };
};

int main()
{
   macierz<int> A(2, 4);
   cout << A << endl;

   macierz<int> B(3, 5);
   for(int i = 0; i < B.wysokosc(); i++)
      for(int j = 0; j < B.szerokosc(); j++)
         B[i][j] = i + j;
   A = B;
   cout << A;

   cin.get();
   return 0;
}
0

no z samym new to nie wiem... ale jak już używać jakiegoś opakowania, to może by tak po prostu:

vector<mojaklasa> array(4, mojaklasa(14, "x", 7.7) );
0
Ranides napisał(a)

no z samym new to nie wiem... ale jak już używać jakiegoś opakowania, to może by tak po prostu:

vector<mojaklasa> array(4, mojaklasa(14, "x", 7.7) );

No i tak też jest w moim kodzie, zerknij na konstruktor macierz::macierz(int, int) ;)

A podział na 'wiersz' i 'wiersz_base' jest po to aby zwiększyć hermetyczność.
Aby móc inicjować lub kopiować całe vector'y ich elementy muszą mieć zdefiniowany publiczny operator=
Jako, że macierz::operator[] zwraca referencję do wiersza, wiersz nie może mieć publicznego operatora przypisania, bo użytkownik mógłby wstawić do macierzy wiersze różnej długości. Stąd klasa 'wiersz_base' z publicznym operatorem przypisania, a sama klasa 'wiersz' niepublicznie dziedziczy po 'wiersz_base' i posiada to co ma być publiczne czyli operator odwołania do konkretnej komórki.

0

a nie powiem kod, ładny, w końcu to uczciwa macierz NxM jest, a nie poj. wektor, albo wektor wektorów...
swoje napisałem ot po to, coby było "punkt programu" widać.
A klasa... gdyby nie to, że polskie nazwy zawiera, to by mi się bardzo podobała ;D

0
adf88 napisał(a)
#include <new>
//...
   wiersz* t = (wiersz*) calloc(m, sizeof(wiersz));
   for(int i=0;i<n;i++) new(&t[i]) wiersz(n); 
//...
   //czyszczenie pamieci
   for(int i=0;y<n;i++) t[i].~wiersz();
   free(t); //czyscimy pamiec

Ale to nie jest zbyt eleganckie rozwiązanie. Lepiej byłoby użyć konstruktora domyślnego (normalne new) i w pętli zmienić rozmiar każdego wiersza na 'n'.

To cię powinno zainteresować:

... SNIP

Nie powiem co, fajnie wymyślone, ale ja też troche nad tym myślałem i poszedłem trochę inna drogą, ale w sumie na to samo wyszlo. Po prostu zrobiłem konstruktor domyślny, który nie robił nic i metode zaalokuj która alokowałą pamiec w wierszu, i potem po prostu ja dla kazdego wiersza wywoływałem. Dzięki za pomoc :) teraz wszystko smiga :)

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