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

Destruktor wywołuje się bezpośrednio po konstruktorze

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
400 wizyt
pytanie zadane 2 kwietnia 2018 w C i C++ przez DarkEliat Bywalec (2,810 p.)

Witam!

Mam taki kod:

class A
{
public:
	A()
	{}
	~A()
	{
		cout << "Destruktor" << endl;
	}
};

class B
{
public:
	B()
	{
		cout << "1" << endl;
	}
	~B()
	{}

	A a;
};

I teraz zacznie robić się śmiesznie:

class C
{
public:
	C()
	{
	
	}
	~C()
	{}

	A a; // Po zakończeniu konstruktora C() wywołuje się destruktor ~A() obiektu 'a'

	B b; // Po zakończeniu konstruktora C() wywołuje się desktruktor ~B(),
		 // a żeby było śmieszniej wywołuje się on jeszcze przed destruktorem obiektu 'a',
		 // dalej wywołany zostaje destruktor ~A() obiektu 'b.a'
};

Wyjaśni mi ktoś co tu się odwala? Z tego co mi było wiadomo, to destruktory są wywoływane przy niszczeniu obiektu (z takim zamysłem napisałem oryginalny kod, który został tutaj przeze mnie bardzo uproszczony), a nie podczas zakończenia konstruktora klasy, w której się omawiany obiekt znajduje.

Kończąc dodam, że finalnie w tym całym kodzie klasa B w ogóle nie będzie występować, ponieważ dodałem ją tutaj dla testów (i jak się okazało przy jej działaniu też dzieje się "magia"). Kod ma wyglądać tak:

// Oczywiście w gigantycznym uproszczeniu
class C
{
public:
	C()
	{
	
	}
	~C()
	{}

	A a;
};

Pozdrawiam.

komentarz 2 kwietnia 2018 przez monika90 Pasjonat (22,940 p.)
edycja 2 kwietnia 2018 przez monika90

Pokaż kod który ma związek z problemem. To są same definicje klas, które same w sobie nie powodują wywołania żadnych konstruktorów czy destruktorów.

wywołuje się on jeszcze przed destruktorem obiektu 'a'

To normalne, podobiekty są niszczone  w odwrotnej kolejności niż są tworzone, a tworzone są w kolejności deklaracji w klasie.

komentarz 2 kwietnia 2018 przez DarkEliat Bywalec (2,810 p.)

Klasa, która odpowiada klasie A:

// Card.h
#pragma once
#include <SFML/Graphics.hpp>
#include "GraphicsController.h"
#include "Caption.h"


using namespace sf;

class Card : public Sprite
{
public:
	Card();
	Card(string textureAndCardName);
	~Card();

	string getCardName();
	void setCard(string textureAndCardName);
	
	vector<string> neighboringCards;

private:
	string textureAndCardName; // Nazwa karty i tekstury karty, który są takie same
	bool addedToDeck;
};

// Card.cpp

#include "Card.h"
#include "Deck.h"



Card::Card()
{
	addedToDeck = false;
}

Card::Card(string textureAndCardName)
{
	setCard(textureAndCardName);
}

Card::~Card()
{
	if(addedToDeck == true)
		Deck::removeCard(textureAndCardName);
}

string Card::getCardName()
{
	return textureAndCardName;
}

void Card::setCard(string textureAndCardNameToSet)
{
	// Przeszukiwanie talii w celu sprawdzenia możliwości dodania karty o podanej nazwie
	unordered_map<string, Card*>::const_iterator iterator = Deck::getDeck()->find(textureAndCardName);

	// Jeśli nie znalazł istniejącej karty o podanej nazwie, to można ją dodać
	if (iterator == Deck::getDeck()->end())
	{
		setImageToSprite(*this, textureAndCardNameToSet);

		this->textureAndCardName = textureAndCardNameToSet;

		Deck::addCard(*this, textureAndCardNameToSet);

		addedToDeck = true;
	}
	else
	{
		cout << convertToPolishChars("Karta o nazwie '" + textureAndCardNameToSet + "' już istnieje! Nie można jej utworzyć ponownie!") << endl;
	}
}

Dodatkowa klasa, która przetrzymuje talię kart:

// Deck.h

#pragma once
#include <unordered_map>
#include "Card.h"

using namespace std;

class Deck
{
public:
	Deck();
	~Deck();

	virtual void virutalFunction() = 0; // Funckja utworzona tylko po to by klasa Deck była klasą abstrakcyjną

	static void addCard(Card &card, string cardName);

	static void removeCard(string cardName);

	static unordered_map<string, Card*> *getDeck(); // Zwraca całą talię kart
	static Card *getCard(string cardName); // Zwraca kartę o podanej nazwie

private:
	static unordered_map<string, Card*> deck;
};
// Decl.cpp

#include "Deck.h"

unordered_map<string, Card*> Deck::deck; // Ta linijka musi się tu znajodwać, bo ten obiekt jest statyczny

Deck::Deck()
{
}


Deck::~Deck()
{
}

void Deck::addCard(Card & card, string cardName)
{
	deck.insert({cardName, &card});
}

void Deck::removeCard(string cardName)
{
	deck.erase(cardName);
}

unordered_map<string, Card*>* Deck::getDeck()
{
	return &deck;
}

Card * Deck::getCard(string cardName)
{
	return deck[cardName];
}

Klasa, która odpowiada klasie C:

//Game.h

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include "GameInfo.h"
#include "GraphicsController.h"
#include "AudioController.h"
#include "File.h"
#include "View.h"
#include "Card.h"
#include "Deck.h"


using namespace sf;
using namespace std;


class Game : project::View
{
public:
	Game();
	Game(RenderWindow &window, GraphicsController &graphicsController, AudioController &audioController, Font &font, GameInfo &gameInfo);
	void run();

private:
	void loadData(); // Ustawia wszystkie tekstury, elementy dźwiękowe itd.
	void pause(); // Pauzuje grę
	void updateScore(int pointsToAdd);

	/////////////////////////////////////////////////////////////////////////
	// Karty
	/////////////////////////////////////////////////////////////////////////
	Card blue1;

	/////////////////////////////////////////////////////////////////////////
	Card bonus;

	/////////////////////////////////////////////////////////////////////////
	Card center5;

	/////////////////////////////////////////////////////////////////////////
	Card extra2;
	Card extra4;

	/////////////////////////////////////////////////////////////////////////
	Card green10;
	Card green13;
	Card green14;
	Card green2;
	Card green6;
	Card green8;
	Card green9;

	/////////////////////////////////////////////////////////////////////////
	Card purple10;
	Card purple12;
	Card purple16;
	Card purple19;
	Card purple20;
	Card purple5;
	Card purple9;

	/////////////////////////////////////////////////////////////////////////
	Card red11;
	Card red14;
	Card red15;
	Card red17;
	Card red18;
	Card red4;
	Card red8;

	/////////////////////////////////////////////////////////////////////////
	Card unlock10;
	Card unlock7;

	/////////////////////////////////////////////////////////////////////////
	Card yellow10;
	Card yellow12;
	Card yellow15;
	Card yellow16;
	Card yellow3;
	Card yellow5;
	Card yellow7;

	/////////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////////

	Caption c_score;

	bool paused;
	bool clicked;
};


#endif // GAME_H_INCLUDED
// Game.cpp
// Funkcje, o których mowa

Game::Game()
{
}

Game::Game(RenderWindow & window, GraphicsController & graphicsController, AudioController & audioController, Font & font, GameInfo & gameInfo)
{
	this->window = &window;
	this->graphicsController = &graphicsController;
	this->audioController = &audioController;
	this->font = &font;
	this->gameInfo = &gameInfo;

	paused = false;
	clicked = false;
	loadedData = false;

	loadData();
	cout << "2";
}

void Game::loadData()
{
	if (window != NULL && graphicsController != NULL &&				 // Jeśli wszystkie niezbędne
		audioController != NULL && font != NULL && gameInfo != NULL) // Obiekty zostały ustawione 
	{
		if (loadedData == false)
		{
			//////////////////////////////////////////////
			// Konfigurowanie kart
			//////////////////////////////////////////////
			blue1.setCard("blue-1");
			//////////////////////////////////////////////
			bonus.setCard("bonus");
			//////////////////////////////////////////////
			center5.setCard("center-5");
			//////////////////////////////////////////////
			extra2.setCard("extra+2");
			extra4.setCard("extra+4");
			//////////////////////////////////////////////
			green10.setCard("green-10");
			green13.setCard("green-13");
			green14.setCard("green-14");
			green2.setCard("green-2");
			green6.setCard("green-6");
			green8.setCard("green-8");
			green9.setCard("green-9");
			//////////////////////////////////////////////
			purple10.setCard("purple-10");
			purple12.setCard("purple-12");
			purple16.setCard("purple-16");
			purple19.setCard("purple-19");
			purple20.setCard("purple-20");
			purple5.setCard("purple-5");
			purple9.setCard("purple-9");
			//////////////////////////////////////////////
			red11.setCard("red-11");
			red14.setCard("red-14");
			red15.setCard("red-15");
			red17.setCard("red-17");
			red18.setCard("red-18");
			red4.setCard("red-4");
			red8.setCard("red-8");
			//////////////////////////////////////////////
			unlock10.setCard("unlock-10");
			unlock7.setCard("unlock-7");
			//////////////////////////////////////////////
			yellow10.setCard("yellow-10");
			yellow12.setCard("yellow-12");
			yellow15.setCard("yellow-15");
			yellow16.setCard("yellow-16");
			yellow3.setCard("yellow-3");
			yellow5.setCard("yellow-5");
			yellow7.setCard("yellow-7");
			//////////////////////////////////////////////
			//////////////////////////////////////////////
			//////////////////////////////////////////////

			loadedData = true;
			cout << "1";
		}
	}
}

Kod działa mniej więcej tak, że po użyciu funkcji Card::setCard(); karcie zostaje nadana tekstura według nazwy, którą przekazaliśmy w konstruktorze. Dalej dodawana jest ona do ogólnej talii. Zamysł jest taki, by destruktor usuwał tę kartę kiedy będzie ona zniszczona, ale nie wcześniej. 

komentarz 2 kwietnia 2018 przez monika90 Pasjonat (22,940 p.)
Ale jak tworzysz ten obiekt klasy Game?
komentarz 2 kwietnia 2018 przez DarkEliat Bywalec (2,810 p.)

Controller.h

#ifndef CONTROLLER_H_INCLUDED
#define CONTROLLER_H_INCLUDED

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include "GameInfo.h"
#include "Game.h"
#include "Menu.h"

using namespace std;
using namespace sf;

class Controller
{
private:

    Controller();
	Controller(const Controller &);

public:
    void run();

	static Controller &getReference();

	RenderWindow *getRenderWindow();
	GraphicsController *getGraphicsController();
	AudioController *getAudioController();
	GameInfo *getGameInfo();
	Game *getGameObject();
	Menu *getMenuObject();
	Font *getFont();

private:
    RenderWindow window;
	GraphicsController graphicsController;
	AudioController audioController;
    GameInfo gameInfo;
	Game game;
	Menu menu;
    Font font;

    void runGame();
    void showFinalScore();
    void showMenu();

	

};

#endif // CONTROLLER_H_INCLUDED

Controller.cpp konstruktor

Controller::Controller()
{
	window.create(VideoMode(GameInfo::widthWindow, GameInfo::heightWindow, 32), GameInfo::gameName, Style::Titlebar | Style::Close);

	loadFont(font, "font/Spring_is_Coming.ttf");

	// Tworzenie obiektu z grą
	game = Game(window, graphicsController, audioController, font, gameInfo);
	cout << "4";
	// Tworzenie obiektu wyświetlającego menu
	menu = Menu(window, graphicsController, audioController, font, gameInfo);

	gameInfo.state = GameInfo::GAME;

    srand(time(NULL));
	
}

 

1
komentarz 2 kwietnia 2018 przez monika90 Pasjonat (22,940 p.)
[code]game = Game(window, graphicsController, audioController, font, gameInfo);[/code]

Tworzony jest obiekt tymczasowy, przypisywany jest do zmiennej game i zaraz potem jest niszczony. To nic dziwnego że destruktor jest wywoływany zaraz po konstruktorze.
komentarz 2 kwietnia 2018 przez DarkEliat Bywalec (2,810 p.)
W życiu bym nie dociekł, że tu leży problem.

Jakiś pomysł jak to rozwiązać (Pomijając tworzenie funckji Game::setGame(argumenty), która by to ustawiała)?
1
komentarz 2 kwietnia 2018 przez monika90 Pasjonat (22,940 p.)

Spróbuj od razu utworzyć obiekt Game za pomocą właściwego konstruktora. Przenieś deklarację game poniżej wszystkich innych składowych i zainicjalizuj

RenderWindow window;
GraphicsController graphicsController;
AudioController audioController;
GameInfo gameInfo;
Menu menu;
Font font;
Game game{window, graphicsController, audioController, font, gameInfo};

to wymaga kompilatora wspierającego co najmniej C++11. Oczywiście usuń to przypisanie do game z konstruktora.

komentarz 2 kwietnia 2018 przez DarkEliat Bywalec (2,810 p.)
Wszystko działa!

Bardzo dziękuję za pomoc.

Jeśli chcesz przepisz Twoją odpowiedź z komentarza do sekcji odpowiedzi i oznaczę to jako Najlepszą odpowiedź ;)

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
2 odpowiedzi 318 wizyt
pytanie zadane 14 sierpnia 2020 w C i C++ przez lujasjeden Użytkownik (860 p.)
–4 głosów
0 odpowiedzi 512 wizyt
pytanie zadane 17 października 2017 w C i C++ przez p1erut Nowicjusz (120 p.)
0 głosów
2 odpowiedzi 297 wizyt
pytanie zadane 13 grudnia 2016 w C i C++ przez klap Początkujący (410 p.)

93,187 zapytań

142,203 odpowiedzi

322,017 komentarzy

62,513 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 2365p. - dia-Chann
  2. 2326p. - Łukasz Piwowar
  3. 2315p. - Łukasz Eckert
  4. 2301p. - CC PL
  5. 2269p. - Tomasz Bielak
  6. 2235p. - Łukasz Siedlecki
  7. 2232p. - rucin93
  8. 2169p. - Marcin Putra
  9. 2006p. - Michal Drewniak
  10. 1946p. - Adrian Wieprzkowicz
  11. 1901p. - Mikbac
  12. 1744p. - rafalszastok
  13. 1734p. - Anonim 3619784
  14. 1586p. - Dawid128
  15. 1487p. - Michał Telesz
Szczegóły i pełne wyniki

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 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...