• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dodawanie obiektów własnych klas do std::vector

Object Storage Arubacloud
0 głosów
1,216 wizyt
pytanie zadane 16 czerwca 2017 w C i C++ przez excavelty Bywalec (2,480 p.)

Od pewnego czasu zmagam się z następującym problemem:

void Game::Update() //w klasie Game znajduje się funkcja Update zawierająca pętlę gry
//korzystam z SFML
{
        std::vector<Object> opps;

       Object tr1(/*wysłanie do konstruktora odpowiednich wartości*/);

       opps.push_back(tr1); //linijka wywołująca błąd, próbowałem również emplace_back()

 	while (app.isOpen())
        {
           sf::Event evnt;
           while (app.pollEvent(evnt))
           {
              //...
           }
              //tutaj następuje wywołanie jakichś funkcji na rzecz innego obiektu
              //w tym miejscu wywoływana jest funkcja Move() na rzecz wszystkich obiektów klasy
             //Object znajdujących się w "opps":

           	for (int i = 0; i < opps.size(); i++)
		{
			 opps[i].Move();
		}

                app.clear();
                //wyświetlenie na ekran(Object dziedziczy z sf::Drawable):
                for (int i = 0; i < opps.size(); i++)
		{
			app.draw(opps[i]);
		}
                app.display();

               //jeżeli spełniony zostanie odpowiedni warunek, to nastąpi
              //wylosowanie lub określenie odpowiednich wartości, które następnie 
             //zostaną przesłane przy definiowaniu kolejnego obiektu klasy Object
            //obiekt ten usiłuję dodać do kontenera:

           Object x(/*wysłanie wyżej wspomnianych wartości*/);
           opps.push_back(x);
        }

}

Po tym wszystkim otrzymuję błąd o kodzie: C2280, o treści:

    'Object::Object(const Object &)': attempting to reference a deleted function'

Próbowałem szukać rozwiązania w Internecie, ale wiele tematów dotyczy użycia unique::ptr.

Czy ktoś mógłby w przystępny sposób wytłumaczyć:

- gdzie tkwi błąd?

- czym różni się dodawanie obiektów własnych klas do kontenera od dodawania obiektów typów wbudowanych?

Bardzo proszę również o możliwe rozwiązania, wcześniej próbowałem zrobić kontener wskaźników i program się

kompilował, ale błąd pojawiał się w momencie dodawania drugiego elementu do std::vector.

komentarz 16 czerwca 2017 przez Evelek Nałogowiec (28,960 p.)
Pokaż jak wygląda Twoja klasa Object (w szczególności składowe oraz konstruktory).

1 odpowiedź

+1 głos
odpowiedź 16 czerwca 2017 przez Żyrosławw Bywalec (2,300 p.)
wybrane 16 czerwca 2017 przez excavelty
 
Najlepsza
Masz "wyłączony" konstruktor kopiujący klasy obiekt. Dodawanie rzeczy do std::vector polega właśnie na tworzeniu kopii obiektu takim konstruktorem. Najprościej dodaj publiczny difoltowy konstruktor kopiujący do Obiekt.
1
komentarz 16 czerwca 2017 przez Evelek Nałogowiec (28,960 p.)
Wypada jeszcze sprawdzić jedno - jeśli ma w składowych wskaźniki z dynamiczną alokacją pamięci lub coś podobnego to defaultowy konstruktor kopiujący będzie niepoprawny.
komentarz 16 czerwca 2017 przez Żyrosławw Bywalec (2,300 p.)
Masz rację, ale jak napisałem to najprostsze rozwiązanie :) . Ewentualnie można używać std::move(), albo zrobić własny konstruktor.
komentarz 16 czerwca 2017 przez excavelty Bywalec (2,480 p.)
edycja 16 czerwca 2017 przez excavelty
public:
	Object(std::string path, float msx = 0.1f, int how_many_tex = 1, float msy = 0.0f,
		int rarerity = 1, bool stable_status = false, float stability = 0.0f);// konstruktor
    Object(const Object&); //co dalej z tym konstruktorem? Pojawiły się inne błędy:

//LNK1120 : 1 unresolved externals
//LNK2019: 
unresolved external symbol "public: __thiscall Object::Object(class Object const &)" 
(??0Object@@QAE@ABV0@@Z) referenced in function "public: void __thiscall std::allocator
<class Object>::construct<class Object,class Object &>(class Object *,class Object &)" (??$construct@VObject@@AAV1@@?$allocator@VObject@@@std@@QAEXPAVObject@@AAV2@@Z)	


//Tutaj funkcje składowe

private:
float msx, msy;
	std::vector<sf::Texture> tex;
    sf::Sprite s;
	std::ostringstream buffor;

	int rarerity_level;
	bool stable;
	float stability;
Object::Object(std::string path, float msx, int how_many_tex , float msy,
	int rarerity, bool stable_status, float stability)
	:msx(msx), msy(msy), stable(stable_status), stability(stability), rarerity_level(rarerity)
{
	for (int i = 0; i < how_many_tex; i++)
	{
		sf::Texture x;
		tex.push_back(x);

		buffor << i + 1;
		tex[i].loadFromFile(path + buffor.str() + ".png");

		buffor.str("");
	}

	s.setTexture(tex[0]);

	next_pos();// ustatnowienie poczatkowych pozycji

}//definicja konstruktora

Edit: wystarczyło dodać klamry, problem chyba rozwiązany, dziękuję za pomoc. Pozostaje jednak pytanie czemu przy użyciu kontenera wskaźników program się kompilował, a błąd pojawiał się później?

1
komentarz 17 czerwca 2017 przez Żyrosławw Bywalec (2,300 p.)
To pokaż jak dokładnie dodawałeś wskaźniki. Może dodawałeś do niego wskaźniki obiektów o zbyt małym zasięgu
komentarz 17 czerwca 2017 przez excavelty Bywalec (2,480 p.)

Faktycznie, jeżeli dodam wskaźniki do obiektów przed pętlą główną gry, to później nie ma problemu. Jak w takim razie poradzić sobie z zasięgiem, jeżeli chciałbym wypełniać kontener, tylko wtedy, gdy zostanie spełniony stosowny warunek:

void Game::Update()
{

Object a(/**/);
Object *c = &a;

std::vector<Object*> opps;
opps.push_back(c); //jeżeli dodam w tym miejscu to później nie ma problemu

 while(/*warunek*/)//pętla gry


 while(/*warunek*/)
 {
   ...
 }

      if(/*warunek*/)
      {
        Object x(/**/);
        Object *w = &x;
        opps.push_back(w);// wypełnienie vectora  tutaj prowadzi później do błędu
        //czy można zapisać to tak: opps.push_back(&x)?
      }

      for(int i = 0; i < opps.size(); i++)
     {
       opps[i]->Move();//przykładowa funkcja wywoływana przez wszystkie wskażniki
       // w "opps"
     }












}
}

 

1
komentarz 17 czerwca 2017 przez Żyrosławw Bywalec (2,300 p.)
operator new i alokowanie na stercie, nie stosie xD

Bo tak to ty robisz lokalny obiekt (na stosie)  który kasowany jest po wyjściu za klamry. Tylko pamiętaj żeby potem zwolnic pamięć
komentarz 17 czerwca 2017 przez excavelty Bywalec (2,480 p.)
Dzięki, teraz działa elegancko.

Podobne pytania

+3 głosów
3 odpowiedzi 990 wizyt
0 głosów
1 odpowiedź 292 wizyt
0 głosów
1 odpowiedź 1,055 wizyt
pytanie zadane 3 września 2016 w C i C++ przez niezalogowany

92,565 zapytań

141,416 odpowiedzi

319,598 komentarzy

61,948 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...