Tarkoitus olisi käydä kaikki oman tekemäni luokan öö.. "lapset" (ei nyt tule mieleen oikeeta termiä. Eli jotenkin näin:
// oma luokka class omaLuokka { public: int i; omaLuokka() { i = 1; } } // tämä koodi pääohjelmassa omaLuokka eka, toka, kolmas, neljas; int summa; summa = kayLapiLuokka(); // summa = 4
Eli jokaisesta "lapsesta" lasketaan tuo muuttuja i ja lisätään se summaan.
Voiko näin tehdä ja miten se olisi helpoin ja järkevin totetuttaa?
E: Kysytään tässä samassa nyt, miten C++:ssa lisätään luokkaan parametrejä (että voisi sitä "lasta" luodessa määritellä tuon luvun i.
En nyt oikeen tiedä miten haluat nuo läpi käydä, mut taulukkoa varmaan haluat? std::vector on juurikin kiva tuollasia varten. Jospa tää kertois jotain:
#include <iostream> #include <vector> // std::vector löytynee täältä class omaLuokka { private: int i; // ei kait tätä oo järkeä pitää publikissa public: // jos ei luokkaa luodessa anneta mitään parametrejä nii laitetaan tällänen hassu arvo i:lle omaLuokka() { i = 1000; }; // ja tälleen mahollistetaan se parametrin anto luokalle omaLuokka(int _i) { i = _i; }; int KayLapi() { // tässä välissä voi laskeskella i:tä, jos sitä ny haluaa vielä muutella return i; }; }; int main() { // luodaan std::vector-härdelli johon luokat voi tunkea ja käydä läpi kivasti std::vector <omaLuokka> luokat; omaLuokka a, b(25), c(100); int summa = 0; // lisätään tavarat vektoriin luokat.push_back(a); luokat.push_back(b); luokat.push_back(c); for(unsigned int j=0; j<luokat.size(); j++) { summa += luokat[j].KayLapi(); } std::cout << summa << std::endl; return 0; }
Kirjotin lennosta, ei oo täyttä varmuutta toimivuudesta.
Siis haluat laskea oman luokan instanssien summan riippumatta siitä, missä ne on luotu? Minäkin kirjoitin lennossa, eli korjaa sinä virheet. ;)
#include <vector> class omaluokka { private: int luku; // Staattisen jäsenen esittely, siis vain yksi muuttuja koko ohjelmassa static std::vector<const omaluokka *> omatluokat; public: omaluokka() { // Kootaan listaa oman luokan instansseista omatluokat.push_back(this); } omaluokka(int _i) { luku = _i; // Lisäys kaikissa eri muodostimissa! omatluokat.push_back(this); } ~omaluokka() { // Poistetaan tuhottavat tapaukset std::vector<const omaluokka *>::iterator i; i = omatluokat.find(this); if (i != omatluokat.end()) { // Siirretään taulun viimeinen löydetyn paikalle ja poistetaan se lopusta // Esim. ABCDE - B => AECDE => AECD *i = *(omatluokat.end() - 1); omatluokat.erase(omatluokat.end() - 1); } } // Staattinen funktio static int summa() { std::vector<const omaluokka *>::iterator i; int s = 0; for (i = omatluokat.begin(); i != omatluokat.end(); ++i) { s += (*i)->luku; } return s; } static int lukumaara() { return omatluokat.size(); } }; // Staattisen jäsenmuuttujan määrittely std::vector<const omaluokka *> omaluokka::omatluokat; #include <iostream> int main() { std::cout << omaluokka::summa() << std::endl; // 0 omaluokka a(7); std::cout << omaluokka::summa() << std::endl; // 7 std::cout << omaluokka::lukumaara() << std::endl; // 1 omaluokka b(9); std::cout << omaluokka::summa() << std::endl; // 16 std::cout << omaluokka::lukumaara() << std::endl; // 2 return 0; }
Huhhuh, on kyllä sellaista hepreaa minulla, että saa nähdä osaanko näitä vinkkejä hyödystää. Noh, kiitos silti molemmille!
Tuossa Metabolixin koodissa on eräs sudenkuoppa, jota kannattaa varoa
omaluokka a(7); omaluokka b = a; std::cout << omaluokka::lukumaara(); // Tulostaa 1
Eli jos luokalla on epätavallinen konstruktori, niin on aina huolehdittava, etteivät kääntäjän automaattisesti luomat kopiointikonstruktorit ja sijoitusoperaattorit aiheuta ongelmia.
Esimerkiksi näin:
class omaluokka { private: omaluokka(const omaluokka &); omaluokka &operator=(const omaluokka &); // ... };
Tai jos boost on käytössä, niin näin:
class omaluokka : public boost::noncopyable // ...
Tämän jälkeen sijoituslauseke a = b;
tuottaa käännösvirheen.
os kirjoitti:
Eli jos luokalla on epätavallinen konstruktori, niin on aina huolehdittava, etteivät kääntäjän automaattisesti luomat kopiointikonstruktorit ja sijoitusoperaattorit aiheuta ongelmia.
Niin, tai tämä yleensä muotoillaan vähän toisin: Jos luokalle täytyy erikseen tehdä destruktori, sijoitusoperaattori tai kopioiva konstruktori, täytyy yleensä tähdä nämä kaikki kolme. Joissakin ohjeissa tätä nimitetään "Kolmen laiksi" (Law of Three).
Jos oikein olen ymmärtänyt, niin noiden os:n neuvomien kopioimiskieltojen jälkeen luokan instansseja ei voi laittaa std::vectoriin (tai varmaan mihinkään STL:n säiliöihin), koska se sisäisesti kopioi alkioita. Eli siis vectoriin pitäisi sitten laittaa osoittimia olioihin.
Käyttävätkö STL-säilöt muuten kopioconstructoria vai sijoitusoperaattoria?
Vai kumpaakin?
Riippuu STL:n toteutuksesta, kuinka paljon sen sisällä käytetään sijoitusoperaattoria. Olennaista kuitenkin on, että STL:n säiliöiden alkioilta vaaditaan C++-standardissa sijoitusoperaattorin järkevä toteutus. Alkioiden pitää noudattaa ns. Assignable-käsitettä.
Koodi, joka ei noudata standardia tässä asiassa voi kyllä toimia joskus ja jossakin. Mutta sellaiseen "toimintaan" ei kannata luottaa, koska vaikkapa kääntäjäsi STL-kirjaston uusi versio voi rikkoa sen. Tuleva C++-standardi C++0x sisältää käsitteet (concepts), jotka mahdollistavat, että tällaiset vaatimukset voi esittää itse koodissa, ja siten kääntäjä voi tarkistaa ne.
Viitteeksi:
http://www.sgi.com/tech/stl/stl_introduction.
Hae Assignable-sanaa.
En oikein tiedä, mikä olisi tällä hetkellä hyvä esittely tulevasta C++:sta ja etenkin käsitteistä. Tässä on PDF, jossa on akateemista tekstiä. Vain tosi kiinnostuneille.
Aihe on jo aika vanha, joten et voi enää vastata siihen.