• 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

VPS Starter Arubacloud
0 głosów
1,412 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 1,211 wizyt
0 głosów
1 odpowiedź 371 wizyt
0 głosów
1 odpowiedź 1,126 wizyt
pytanie zadane 3 września 2016 w C i C++ przez niezalogowany

93,078 zapytań

142,042 odpowiedzi

321,446 komentarzy

62,423 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

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...