Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: luokan läpikäyminen

Sivun loppuun

punppis [12.05.2008 02:19:00]

#

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.

Spongi [12.05.2008 04:42:02]

#

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.

Metabolix [12.05.2008 08:15:05]

#

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;
}

punppis [12.05.2008 08:59:07]

#

Huhhuh, on kyllä sellaista hepreaa minulla, että saa nähdä osaanko näitä vinkkejä hyödystää. Noh, kiitos silti molemmille!

os [12.05.2008 21:03:25]

#

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.

koo [13.05.2008 18:53:36]

#

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).

TsaTsaTsaa [13.05.2008 19:37:08]

#

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.

Mazzimo [13.05.2008 23:28:37]

#

Käyttävätkö STL-säilöt muuten kopioconstructoria vai sijoitusoperaattoria?
Vai kumpaakin?

Pekka Karjalainen [14.05.2008 10:50:59]

#

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.html

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.

http://www.research.att.com/~bs/popl06.pdf


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta