[c++] Problem z pewnym konstruktorem /+const [] member

0

Witam mam pewien problem z konstruktorem, oto moja klasa:

class Wektor
{        
    float wek[2]; // przechowywanie współrzędnych wektora dlugosci
    
  
  public:                          
   Wektor  operator  +  (Wektor);   
    float   operator   [ ] (unsigned int indeks) const; // przeciazenie operatorow [] 
    float & operator   [ ] (unsigned int indeks);              // przeciazenie operatora+ dodaje do siebie dwa wektory   
};
float Wektor::operator [ ] (unsigned int indeks) const
{ 
   if(indeks<0 || indeks>=3) 
   return wek[0]; // sprawdza czy podane indeksy sa prawidlowe jesli nie zwraca wyraz[0] jesli tak wyraz[indeks]
   return wek[indeks];
}
 
  
float & Wektor::operator [ ] (unsigned int indeks)
{ 
   if(indeks<0 || indeks>=3) 
   return wek[0]; 
   return wek[indeks];
}

Wektor Wektor::operator + (Wektor w1) 
{
  Wektor suma;
  int i;
  for (i=0;i<2;i++) suma[i]=(*this)[i]+w1[i]; 
  return suma;
}  

W tej postaci wszystko sie kompiluje. Potrzebuje wyzerowac na początku tablice wek gdyz jedna z wartosci ma byc =0, a nie zaszkodzi wyzerowac calej, tak wiec dodaje w czesci public moj konstruktor:

Wektor (float wek[2]){wek[0]=0;wek[1]=0;}; 

nie jestem pewien czy jest on poprawny, ale po jego dodaniu przy probie kompilacji otrzymuje komunikat:
C:\Users\Desktop\x.cpp In member function Wektor Wektor::operator+(Wektor)': 48 C:\Users\\Desktop\x.cpp no matching function for call to Wektor::Wektor()'
note C:\Users\Desktop\x.cpp:11 candidates are: Wektor::Wektor(const Wektor&)
note C:\Users\Desktop\x.cpp:11 Wektor::Wektor(float*)

0
Wektor ():wek[0](0),wek[1](0){}; 

raczej o coś takiego potrzebujesz

0

oj nie zapomniales o jakichs nawiasach?

0

kompilator wywala bledy po wstawieniu tego konstruktora

0

Kompilator wywala błędy ponieważ na liście inicjalizacyjnej znajdują się nie składniki klasy tylko poszczególne elementy składnika (tak mi się wydaje). Gdy zmienisz na coś takiego

	Wektor::Wektor()
	{
	wek[0] = 0;
	wek[1] = 0;
	};

Powinno pójść. Tylko teraz tak z ciekawości. Czy istnieje w C++ sposób aby zainicjalizować agregat na liście inicjalizacyjnej? Tutaj akurat tablica nie jest stałą wiec to co napisałem przejdzie. Ale gdyby składnik wek był stały to już nie wiem jak można by to zrealizować.

0
Tattva napisał(a)

Czy istnieje w C++ sposób aby zainicjalizować agregat na liście inicjalizacyjnej?

Lista inicjalizacyjna to ciąg wywołań konstruktorów, czy tablica posiada (pseudo)konstruktor? Nie? No właśnie...

0
 #include <iostream>

class X{ int tablica[69]; int acilbat[96]; };

struct __Y_dummybase { __Y_dummybase const & set(int* target, size_t idx, int value) const { return target[idx] = value, *this; } };

class Y : private __Y_dummybase
{
public:
	int tablica[69];
	int acilbat[96];

	Y() :
		__Y_dummybase(__Y_dummybase()
			.set(tablica,  1, 100).set(tablica, 10, 1234).set(tablica, 13, 987)
			.set(acilbat,  5, 321).set(acilbat, 60, 1454).set(acilbat, 31, 987)
		)
	{
	}
};

int main()
{
	using namespace std;
	cout << sizeof(X) << " vs " << sizeof(Y) << endl;
	
	Y test;
	cout << test.tablica[13] << " vs " << test.acilbat[31] << endl;
}

klasę X dodałem, żeby było widać, że nic to nie kosztuje, przynajmniej poki o rtti nie rozmawiamy, ekstra prywatna klasa bazowa dodaje dokladnie zero bajtów rozmiaru. klase dummybase/metode set mozna sobie przerobic na template, ktory bedzie nie tylko inty, ale dowolne T przypisywal, ba, mozna dorobic ekstra metody do robienia czegokolwiek, w dowolnej kolejnosci, etc, etc..

bottom line is: ...jednak jest drobny dowcip w tym, ze rownie dobrze moglbys napisac wewnatrz konstruktora tablica[5]=6; itd, gdyz powyzszy mój przykład NIE JEST INICJALIZACJĄ tylko bardzo udziwnionym przypisaniem

wiec po co takie cos? od wszystkich nietrywialnych rzeczy jest ciało konstruktora. prosciej, wygodniej, bez trickow..

0

W przypadku zwykłej tablicy to oczywiście o wiele lepiej umieścić to w ciele konstruktora , choćby ze względu na czytelność.
Ja miałem na myśli taką sytuacje.

class TabConst
{
	const int tab[10];
	TabConst();
};

Nie wiem po prostu w jaki sposób nadać wartości elementom tab. Można oczywiście zawrzeć tab w innej klasie i w konstruktorze tamtej klasy umieścić inicjalizacje tab. Ale ja zastanawiam się czy C++ dostarcza jakiś mechanizm rozwiązania tego problemu że tak powiem bezpośrednio. Z tego co tutaj napisano wynika że nie. Innymi słowy pomimo że wolno nam zadeklarować taki składnik to jest on nie do użycia.

0

fakt, to przykro wyglada i blokuje 99% normalnej inicjalizacji
jednak "oczywiscie" że jest do użycia, tylko brzydsiejszego..

class TabConst
{
        const int tab[10];
        TabConst()
        {
              int* wtf = const_cast<int*>(tab);
              for(int i=0;i<10; ++i)
                  wtf[i] = i;
        }
};
0

Też sądziłem że tak powinno przejść ale w tym problem że próbowałem tą metodą i nie da rady :). Wydaje mi się że według standardu powinien to przepuścić ale kompilator wypluwa błąd:

error C2439: 'TabConst::tab' : member could not be initialized

I to nie tylko Visualowy ale GCC też. Co zabawne ten błąd otrzymujemy gdy tylko zaczniemy pisać jakiekolwiek ciało konstruktora. Innymi słowy kompilator przepuszcza takie coś:

class TabConst
{
	const int tab[10];
public:
        TabConst();	
};

Ale już na taki kod nie pozwoli:

class TabConst
{
	const int tab[10];
public:
	TabConst(){};  // << zmiana w tej linii	
};

Więc nie tylko taki składnik jest nie do użycia ale też klasa która zawiera taki składnik nie może mieć zdefiniowanego konstruktora.

0

no, szare komorki zaskoczyly mi w koncu.
problem jest taki:

*) jezeli nie podasz konstruktora, kompilator wygeneruje domyslny, o ile jest to mozliwe.
*) sprobuj swojego kodu z const-array BEZ podawania konstruktora. kompilator powinien walnac bledem innym - ze nie ma konstruktora. tak jest u mnie na VS2008 przy probie UZYCIA klasy TabConst, nie przy jej definicji
-> konstruktora nie ma, gdyz kompilatorowi nie udalo sie go wygenerowac

*) C++ wymaga, aby kazde pole const jakie znajduje sie w klasie zostalo zainicjowane w konstruktorze, na jego liscie inicjalizacyjnej
*) nie mozliwe jest inicjowanie elementow tablic na tejże
*) tablica int const [5] == const int[5] definiuje stałą skladową klasy. wymaga wiec ona inicjalizacji - niemożliwej ex-def, stad komunikat ze cannot initialize member, wiec kompilatorowi nie udaje sie wygenerowac ctora domyslnego, a Tobei pozniej - nie udaje sie go napisac tak by zostal przyjety..

moim zdaniem, fail specyfikacji. jezeli pole typu const czy const element tablicy jest prymitywem, pod'em, lub typem posiadajacym ctor domyslny, to inicjalizacja powinna sie udac autoamtycznie, wbrew niemozliwosci jej podania na liscie in. kurde, ostatecznie piszac new X[10] odpalamy niejawnie 10x defctor, wiec czemu tutaj wymagac explicite jakies niemozliwej inicjalizacji elementow zamiast uzyc niejawnie defctora co by bylo normalnym, klasycznym zachowaniem sie dla elementow tablic? bezsens.. jesli ktos widzial gdzies kiedys jakies wyjasnienie tej "blokady" pochodzace "od góry" rzadzacej c++'em, bylbym wdzieczny bardzo za wskazanie..

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