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

[C++] Wywoływanie nieprzeciążonego konstruktora z przeciążonego.

Object Storage Arubacloud
0 głosów
199 wizyt
pytanie zadane 24 listopada 2015 w C i C++ przez enther Nowicjusz (240 p.)

Cześć laugh Przerabiam sobie książkę "Od zera do gier kodera" i mam mały problem z jednym programem. Książka jest dość "stara" bo z 2004 i pewnie nie wszystko co tam zostało zaprezentowane jest zgodne z dzisiejszymi standardami, dlaczego chciałbym rozwiać wątpliwości Oto kod:

PLIK main.cpp
// Polymorphism - wykorzystanie techniki polimorfizmu

#include <iostream>
#include <conio.h>
#include "documents.h"

int main()
{
	std::cout << "   POLIMORFIZM   " << std::endl;
	std::cout << "-----------------" << std::endl;

	// wskaźnik na obiekty dokumentów
	CDocument* pDokument;

	// pierwszy dokument - internetowy
	std::cout << std::endl << "--- 1. pozycja ---" << std::endl;
	pDokument = new COnlineDocument("Regedit",
									"Cyfrowe przetwarzanie tekstu",
									"http://programex.risp.pl/?"
									"strona=cyfrowe_przetwarzanie_tekstu");
	pDokument->PokazDane();
	delete pDokument;

	// drugi dokument - książka
	std::cout << std::endl << "--- 2. pozycja ---" << std::endl;
	pDokument = new CBook("Sam Williams", "W obronie wolnosci", "83-7361-247-5");
	pDokument->PokazDane();
	delete pDokument;

	getch();
}

document.h

// Plik nagłówkowy z definicjami klas dokumentów

#include <string>
#include <time.h>

// klasa dowolnego dokumentu
class CDocument
{
	protected:
		// podstawowe dane dokumentu
		std::string	m_strAutor;		// autor dokumentu
		std::string	m_strTytul;		// tytuł dokumentu
		tm			m_Data;			// data stworzenia
	public:
		// konstruktory
		CDocument()
			{ m_strAutor = m_strTytul = "???";
			  time_t Czas = time(NULL); m_Data = *localtime(&Czas); }
		CDocument(std::string strTytul)
			{ CDocument(); m_strTytul = strTytul; }
		CDocument(std::string strAutor, std::string strTytul)
			{ CDocument();
			  m_strAutor = strAutor;
			  m_strTytul = strTytul; }

	//------------------------------------------------------------------------------------	

	// metody
	virtual void PokazDane();
	
	// metody dostępowe do pól
	std::string	Autor()	const	{ return m_strAutor; }
	std::string Tytul()	const	{ return m_strTytul; }
	tm			Data()	const	{ return m_Data;	 }
};

//----------------------------------------------------------------------------------------	

// dokument internetowy
class COnlineDocument : public CDocument
{
	protected:
		std::string	m_strURL;	// adres internetowy dokumentu
	public:
		// konstruktory
		COnlineDocument(std::string strAutor, std::string strTytul)
			{ m_strAutor = strAutor; m_strTytul = strTytul; }
		COnlineDocument(std::string strAutor,
						std::string strTytul,
						std::string strURL)
			{ m_strAutor = strAutor;
			  m_strTytul = strTytul;
			  m_strURL   = strURL;   }

	//------------------------------------------------------------------------------------	

	// metody
	void PokazDane();	// wirtualna metoda przedefiniowana z CDocument

	// metody dostępowe do pól
	std::string	URL()	const	{ return m_strURL; }
};

// książka
class CBook : public CDocument
{
	protected:
		std::string	m_strISBN;	// numer ISBN książki
	public:
		// konstruktory
		CBook(std::string strAutor, std::string strTytul)
			{ m_strAutor = strAutor; m_strTytul = strTytul; }
		CBook(std::string strAutor,
			  std::string strTytul,
			  std::string strISBN)
			{ m_strAutor = strAutor;
			  m_strTytul = strTytul;
			  m_strISBN  = strISBN; }

	//------------------------------------------------------------------------------------	

	// metody
	void PokazDane();	// także wirtualna, przedefiniowana metoda

	// metody dostępowe do pól
	std::string ISBN()	const	{ return m_strISBN; }
};

document.cpp

// Modu³ implementuj¹cy klasy dokumentów

#include <iostream>
#include "documents.h"


/*---------------------------------------------------------------------------------------
   CDocument - implementacja klasy
  ---------------------------------------------------------------------------------------*/

void CDocument::PokazDane()
{
	// wyœwietlenie autora
	std::cout << "AUTOR: ";
	std::cout << m_strAutor << std::endl;

	// pokazanie tytu³u dokumentu
	// (sekwencja \" wstawia cudzys³ów do napisu)
	std::cout << "TYTUL: ";
	std::cout << "\"" << m_strTytul << "\"" << std::endl;

	// data utworzenia dokumentu
	// (pDokument->Data() zwraca strukturê typu tm, do której pól
	//  mo¿na dostaæ siê tak samo, jak do wszystkich innych - za
	//  pomoc¹ operatora wy³uskania . (kropki))
	std::cout << "DATA : ";
	std::cout << m_Data.tm_mday << "." << (m_Data.tm_mon + 1) << "."
			  << (m_Data.tm_year + 1900) << std::endl;
}


/*---------------------------------------------------------------------------------------
   COnlineDocument - implementacja klasy
  ---------------------------------------------------------------------------------------*/

void COnlineDocument::PokazDane()
{
	// najpierw pokazujemy dane odziedziczone z CDocument,
	// wiêc wywo³ujemy wersjê metody pochodz¹c¹ z tej klasy
	CDocument::PokazDane();

	// dalej wyœwietlamy URLa
	std::cout << "URL  : ";
	std::cout << m_strURL << std::endl;
}


/*---------------------------------------------------------------------------------------
   CBook - implementacja klasy
  ---------------------------------------------------------------------------------------*/

void CBook::PokazDane()
{
	// wyœwietlamy dane z CDocument
	CDocument::PokazDane();

	// pokazujemy numerek ISBN
	std::cout << "ISBN : ";
	std::cout << m_strISBN << std::endl;
}

Pierwsze pytanie odnosi się do pliku main.cpp, a konkretnie chodzi mi o to że podczas kompilacji wyskakuje ostrzeżenie: main.cpp|23|warning: deleting object of polymorphic class type 'CDocument' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]| Co dokładnie trzeba zrobić by rozwiązać ten problem?

Drugie tyczy się konstruktorów z klasy CDocument w pliku document.h przeciążony operator wywołuje nieprzeciążony, który ustawia datę, ale gdy chciałem stworzyć obiekt z klasy CDocument z dwoma parametrami, albo jednym to wywołanie bezparametrowego konstruktora najwyraźnej nic nie daje bo jako data ustawione są jakieś bilionowe liczby. Czy teraz działa to jakoś inaczej?laughPoza tym znacie jakieś inne tak szczegółowe kursy C++ jak "Od zera do gier kodara"?

2 odpowiedzi

0 głosów
odpowiedź 24 listopada 2015 przez adrian17 Ekspert (344,860 p.)

o dokładnie trzeba zrobić by rozwiązać ten problem?

Uczyń destruktor klasy bazowej wirtualnym.

wywołanie bezparametrowego konstruktora

Bo tak się tego nie robi, nie wierzę by książka popełniła tak duży błąd. Wywołanie konstruktora jak funkcję nie modyfikuje Ci obiektu, tylko robi nowy obiekt z którym nic nie robisz. Kaskadę konstruktorów pisze się tak:

CDocument(std::string strTytul)
    : CDocument()
{ m_strTytul = strTytul; }

// jeszcze lepiej:

CDocument(std::string strTytul)
    : CDocument(),  m_strTytul(strTytul)
{}

Swoją drogą: nie wywołujesz "konstruktora nieprzeciążonego z przeciążonego", albo jest jeden "nieprzeciążony" albo kilka przeciążonych.

(i zabierz ten przedrostek "C" z klas...)

komentarz 25 listopada 2015 przez enther Nowicjusz (240 p.)

Sorry za dobule post ale jeszcze nie ogarniam tego formu ;D

Umiściłem na końcu deklaracji klasy CDocument:  virtual ~CDocument(); Ale pojawiają się liczne błędy:

||=== Build: Debug in polymorhism (compiler: GNU GCC Compiler) ===|
obj\Debug\documents.o||In function `ZN5CBookD1Ev':|
documents.h|68|undefined reference to `CDocument::~CDocument()'|
documents.h|68|undefined reference to `CDocument::~CDocument()'|
obj\Debug\documents.o||In function `ZN15COnlineDocumentD1Ev':|
documents.h|42|undefined reference to `CDocument::~CDocument()'|
documents.h|42|undefined reference to `CDocument::~CDocument()'|
obj\Debug\documents.o:documents.cpp:(.rdata$_ZTV9CDocument[__ZTV9CDocument]+0xc)||undefined reference to `CDocument::~CDocument()'|
obj\Debug\documents.o:documents.cpp:(.rdata$_ZTV9CDocument[__ZTV9CDocument]+0x10)||undefined reference to `CDocument::~CDocument()'|
obj\Debug\main.o||In function `ZN9CDocumentC1ESsSs':|
documents.h|22|undefined reference to `CDocument::~CDocument()'|
||=== Build failed: 7 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|

0 głosów
odpowiedź 24 listopada 2015 przez enther Nowicjusz (240 p.)

Umiściłem na końcu deklaracji klasy CDocument:  virtual ~CDocument(); Ale pojawiają się liczne błędy:

||=== Build: Debug in polymorhism (compiler: GNU GCC Compiler) ===|
obj\Debug\documents.o||In function `ZN5CBookD1Ev':|
documents.h|68|undefined reference to `CDocument::~CDocument()'|
documents.h|68|undefined reference to `CDocument::~CDocument()'|
obj\Debug\documents.o||In function `ZN15COnlineDocumentD1Ev':|
documents.h|42|undefined reference to `CDocument::~CDocument()'|
documents.h|42|undefined reference to `CDocument::~CDocument()'|
obj\Debug\documents.o:documents.cpp:(.rdata$_ZTV9CDocument[__ZTV9CDocument]+0xc)||undefined reference to `CDocument::~CDocument()'|
obj\Debug\documents.o:documents.cpp:(.rdata$_ZTV9CDocument[__ZTV9CDocument]+0x10)||undefined reference to `CDocument::~CDocument()'|
obj\Debug\main.o||In function `ZN9CDocumentC1ESsSs':|
documents.h|22|undefined reference to `CDocument::~CDocument()'|
||=== Build failed: 7 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|

 

komentarz 25 listopada 2015 przez adrian17 Ekspert (344,860 p.)
Zadeklarowałeś destruktor, ale go nie zdefiniowałeś. Zrób pustą implementację, po prostu dodaj {}.

Podobne pytania

0 głosów
2 odpowiedzi 200 wizyt
pytanie zadane 30 grudnia 2015 w C i C++ przez nemezisso Użytkownik (860 p.)
0 głosów
3 odpowiedzi 188 wizyt
pytanie zadane 31 marca 2020 w C i C++ przez Adalm Początkujący (290 p.)
0 głosów
1 odpowiedź 363 wizyt
pytanie zadane 22 grudnia 2019 w C i C++ przez Jacuchna0 Użytkownik (640 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 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!

...