Konstans inicializálása konstruktor után?

 ( BaT | 2010. április 30., péntek - 19:54 )

Üdv!

Van egy C++ osztályom, aminek van egy privát adattagja, ami konstans. Nyilván ezt inicializálni kell a konstruktorban, ami nem is lenne probléma, csakhogy én szeretnék írni az osztálynak egy operator>>-t is. Viszont ez már eleve egy példány referenciáját veszi át, azaz a konstruktor már lefut azelőtt, hogy beolvasnám az értéket, amit megadnék a konstansnak. Kódban:

#include 

using namespace std;

class Osztaly
{
private:
	const int max;
	//van itt más is
public:
	Osztaly(const int m) :max(m) {}
	//van itt más is
}

istream& operator>>(istream& i,const Osztaly& o)
{
	int m;

	i >> m;
	
	//???

	o.max=m;	//nem jó, max már kapott értéket
	
	o=Osztaly(m);	//nem jó, akkor az operator=-t kellene úgy megírni, hogy max-ot megváltoztassa

	delete o;
	Osztaly o=Osztaly(m);	//nem jó, o egy referencia, ezt nem tehetem meg vele (tudtommal)

	return i;
}

Két workaround is eszembe jutott (max nem konstans, o nem referencia hanem pointer), de ezeket csak akkor választanám, ha tényleg nincs más megoldás.

Ha valakinek van ötlete, ne tartsa magában. Köszönöm!

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Elso! :p

#hup.hu-n imp és nagyz meggyőzött, hogy ez így sehogy nem fog menni, viszont ehelyett proxyosztályt javasoltak. Mivel eddig ez tűnik a legjobb megoldásnak, valószínűleg így fogom csinálni.

--
Don't be an Ubuntard!

<imp> en inkabb azt mondom, hogy a >> legyen ugyanolyan, mint egy copy assignment
<BaT_> mondjuk en is csak egyszer lattam ilyen proxys megoldast, irni meg soha nem irtam
<imp> vagy ne a streamrol olvasd a maxot
<imp> egyebet nem tudok elmondani
<nagyz> +1

De a proxyt is te mondtad. ;)

--
Don't be an Ubuntard!

igen, de ez nem jelenti azt, hogy ilyen insane dolgokat le is programozz:)

altalaban kerulendo a const es ref member.
nem trivialis a msolasuk, ertekadasuk...

Van itt egy olyan ellentmondás, hogy egyrészt te azt mondod, hogy ez a max konstans, tehát az objektum teljes élettartama alatt változatlan, aztán viszont akarsz írni egy fv-t ami megváltoztatja.
Értem én, hogy ez a szerencsétlen fv pont beolvasni szeretne, de ez azon nem változtat, hogy egy meglévő objektumot szeretnél változtatni.

A mutatós megoldás sem jó, hacsak nem mutató referenciát adsz át. (Hogy ez mennyire használhatatlan lenne azt inkább hagyjuk...)

Vagy az operator>>-ról vagy a const-ról le kell mondanod. (Vagy trükköznöd kell egy mutatóval, amit akár egy proxy osztállyal elfedhetsz de attól még felesleges önszopatás.)

Én a const-ot dobnám, de egy Object readObject(iostream&); fv is működhet.
(Vagy static Object Object::read(iostream&);)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

A const_cast nem jó erre?
Így gondoltam:

#include 

class A {
  const int a;
public:
  A(int _a) : a(_a) {}
  void setA(int _a) { *(const_cast< int* > (&a)) = _a; }
  void print() { std::cout << a << std::endl; } 
};

int main()
{
  A a(12);
  a.print();
  a.setA(36);
  a.print();
  return 0;
}

A const_cast (de a dynamic_cast is) tervezési hibára utal, és csak a legvégső esetben megengedett, illetve illik tőle minél előbb megszabadulni, ha lehet.

Egy szóval sem mondtam, hogy szép, de a konkrét problémára egy megoldási lehetőség.

Megjegyzem, néha kimondottan jól jönne, amikor ugyan a konstruktorban akarsz neki értéket adni, mert változatlan az objektum élete során, de ezt nem tudod megtenni az inicializálási listában, mert a konstruktoron belül mondjuk egy picit bonyolultabb számítás eredményeképpen kapnád meg a kívánt értéket.

Static member function, vagy bármi, amit el tudsz képzelni, de még akkor is inkább legyen nem const a member, minthogy const_cast-olni kelljen; ez nálam nem bocsánatos bűn:)
A const memberek szerintem egyébként is talán csak const T& -ként praktikusak.

Nagyon nem szereted te a constot, látom már.. :)
Pedig a const szép dolog, bár a const_cast tényleg gány.

A const correctness hasznos dolog, és nincs is vele bajom, a const memberváltozó viszont szerintem nem annyira praktikus. A kettő nem ugyanaz.

Bár feltehetően ez amit írtál működne, mivel az a változó valószínűleg konkrétan létezik mint memóriaterület valami elérhető helyen, tudtommal valódi constról lekasztolni a const-t az undefined behavior, nem csak rossz stílus.

----
Hülye pelikán