Nyt on todennäköisesti simppeli kysymys ja mulla on vain syntaksi hukassa.
Haluaisin luoda luokasta olioita silmukassa, niin että olioiden nimet tulee indeksimuuttujan perusteella olio0, olio1, olio2 jne.
Olioita ei tule montaa, joten niiden esittely hoituisi käsipelilläkin, mutta myöhemmin täytyisi päästä käsiksi olioiden muuttujiin.
Virheellisellä syntaksilla luotu koodi varmaa valaisee paremmin mitä ajan takaa:
for (int i = 0; i <= 5; i++) { omaluokka (olio+i); //luo oliot "olio0, olio1, ... olio4 } void funktio(int k) { //jos funktion parametri on esim. k=2, asetetaan olio2 muuttujan arvo (olio+k).muuttuja = 66; }
int num_oliot = 5; omaluokka *oliot = new omaluokka[num_oliot]; //Varataan muistia taulukolle jonka koko on num_oliot for(int i = 0; i < num_oliot; i++) { oliot[i]->muuttuja = 66; //Asetetaan indeksin i arvoksi 66 } delete[] oliot;
Tampio kirjoitti:
for (int i = 0; i <= 5; i++) { omaluokka (olio+i); //luo oliot "olio0, olio1, ... olio4 }
Yo. silmukka loisi 6 oliota, eli nollasta viiteen.
Käytä vector
ia.
#include <vector> // - - std::vector<omaluokka> oliot(5); // luodaan 5 oliota oliot[n].toimi(); // käytä n:ttä oliota // tai esim. (jos silmukkaa haluat siis käyttää) std::vector<omaluokka> oliot; // voi olla esim. globaali määrittely, jos tosiaan sellaista haluat käyttää for (int i = 0; i < 5; ++i) oliot.push_back(omaluokka(i));
--
Kuvailemallasi tavalla nimettyjä muuttujia et voi silmukassa luoda. Vastaavaan tarkoitukseen käytetään aina taulukoita tai taulukon kaltaisia muuttujia (kuten vectoria), ja indekseihin viitataan siis (mm.) syntaksilla muuttuja[N] (ei koskaan esim. muuttujaN)
Olennaiset ymmärrettävät asiat tässä ovat nämä:
1. Oliolla ei useinkaan ole ohjelman aikana nimeä, johon voisi viitata, vaan tuo "nimi" on vain koodissa esiintyvä sana, jolla kyseinen olio ohjelmoidessa ja käännettäessä yksilöidään. Nimet yleensä poistetaan linkityksen yhteydessä, koska sen jälkeen ne ovat turhia. Niitä voidaan poikkeuksellisesti säilyttää, jos niitä tarvitaan myöhemmin dynaamisen linkityksen yhteydessä (DLL-tiedostoissa) tai jos koodista on tallennettu erillistä debug-infoa debuggeria varten. Tällöinkin nimet on silti määritelty käännösvaiheessa eikä kesken ohjelman.
2. Käyttämäsi +-merkki ei missään tilanteessa voi tuottaa objektin nimeä, ja vain erityisten apuluokkien kanssa olisi muutenkaan mahdollista yhdistää luku +-merkillä johonkin (paitsi yhteenlaskussa).
Oikea ratkaisu ongelmaasi on luultavasti vector-luokan käyttö, kuten yllä esitettiin.
Vielä lähemmäs alkuperäistä koodiasi voisit päästä myös liittämällä ohjelmallisesti oliosi tiettyyn tekstiin tai lukuun. Tällöin voisit käyttää map-luokkaa ja tehdä sen ympärille tarvittavat apufunktiot:
#include <map> #include <stdexcept> class omaluokka { int muuttuja; // yms. private: static std::map<int, omaluokka> oliot; public: static omaluokka& luo(int i) { if (oliot.find(i) != oliot.end()) { throw std::runtime_error("Olio on jo!"); } // Jos erityiset konstruktoriparametrit ovat tarpeen: // oliot[i] = omaluokka(x, y, z); return oliot[i]; } static omaluokka& hae(int i) { if (oliot.find(i) == oliot.end()) { throw std::runtime_error("Oliota ei ole!"); } return oliot[i]; } static void tuhoa(int i) { if (oliot.find(i) == oliot.end()) { throw std::runtime_error("Oliota ei ole!"); } oliot.erase(oliot.find(i)); } }; std::map<int, omaluokka> omaluokka::oliot;
for (int i = 0; i < 10; ++i) { omaluokka::luo(i); } omaluokka::hae(3).muuttuja = 10; for (int i = 0; i < 10; ++i) { omaluokka::tuhoa(i); }
Tämä ratkaisu ei luultavasti ole järkevä tarpeisiisi, mutta voit silti oppia tästä jotain mm. viittauksista (koodin &-merkit) ja luokkien staattisista jäsenistä.
No voi veljet. Kai se täytyy kertoa enemmän taustoja ongelman takaa. Kehitysalustana on Visual Studio 2008, ja itseasiassa ensiksi koitin juuri luoda arrayta niille olioille, ja siinähän tuli joku mystinen ongelma jota sitten yritin kiertää tuolla alussa kuvailemallani tavalla. Arrayn sain tehtyä mielestäni tismalleen oikein, ohjelma kääntyi ja käynnistyikin nätisti, mutta kun array luodaan ja yrittää muuttaa yhden olion muuttujan arvoja, joko suoraan sijoittamalla tai kyseiseen luokkaan tehdyn funktion välityksellä, niin ohjelmahan kaatuu ja heittää virheilmoituksen "Object reference not set to an instance of an object". Luokan muodostimessa arvoja sai asetettua.
Arrayn loin näin:
array<omaluokka ^> ^ taulukko = gcnew array<omaluokka ^>(10); taulukko[0]->muuttuja = "haloo"; //tässä kaatuu
Ongelma on kait jossain pintaa syvemmällä, joko ohjelmassa tai minun ymmärryksessäni. Täytyy tuota vectoria testata kunhan tästä kotiudun.
Nythän on niin, että luot tuossa taulukollisen osoittimia etkä lainkaan olioita niiden taakse. En tunne C++/CLI:a, mutta normaalin C++:n kanssa kehottaisin ottamaan osoitinmerkin (tässä tapauksessa ^-merkki) pois omaluokka-kohtien perästä ja käyttämään nuolen (->) sijaan pistettä.
array<omaluokka>^ taulukko = gcnew array<omaluokka>(10);
Jos tämä ei kyseisessä kielenkuvatuksessa ole mahdollista, joudut vielä luomaan nuo oliot silmukassa erikseen:
array<omaluokka^>^ taulukko = gcnew array<omaluokka^>(10); for (int i = 0; i < 10; ++i) { taulukko[i] = gcnew omaluokka(); }
Miten on tuhoamisen tai muun vapauttamisen laita tuon GC:n kanssa, sitä en tiedä.
Jos taulukon koko tunnetaan, ei sitä varmaankaan kannata dynaamisesti varata:
array<omaluokka> taulukko(10); // vai kuinka lie?
Ja kun kerran C++/CLI on käytössä, mahtaako tuossa edes olla C++:n standardikirjastoa? Kannattaa muistaa, että C++/CLI on niin suurelta osin jo oma kielensä eikä C++:n laajennos, että tämäkin keskustelu sopisi oikeastaan paremmin muiden kielten alueelle. Korjasin otsikon todellisen kielen mukaiseksi.
Metabolix kirjoitti:
Jos tämä ei kyseisessä kielenkuvatuksessa ole mahdollista, joudut vielä luomaan nuo oliot silmukassa erikseen:
array<omaluokka^>^ taulukko = gcnew array<omaluokka^>(10); for (int i = 0; i < 10; ++i) { taulukko[i] = gcnew omaluokka(); }
No nyt. Tuon jälkeen homma toimii. Kiitos kovasti tästä, nyt kohti uusia vastoinkäymisiä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.