• 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

VPS Starter Arubacloud
0 głosów
248 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 223 wizyt
pytanie zadane 14 sierpnia 2020 w C i C++ przez lujasjeden Użytkownik (860 p.)
–4 głosów
0 odpowiedzi 439 wizyt
pytanie zadane 17 października 2017 w C i C++ przez p1erut Nowicjusz (120 p.)
0 głosów
2 odpowiedzi 232 wizyt
pytanie zadane 13 grudnia 2016 w C i C++ przez klap Początkujący (410 p.)

92,455 zapytań

141,263 odpowiedzi

319,099 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...