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

Dziedziczenie-tablica wskaźników na klasę, która nie jest klasą bazową dla innych.

Object Storage Arubacloud
0 głosów
263 wizyt
pytanie zadane 18 lipca 2018 w C i C++ przez chucksqll Stary wyjadacz (12,930 p.)
edycja 18 lipca 2018 przez chucksqll

Witam.

Piszę pewien program w ramach zadania(rozdział 17 zadanie nr 6 szkoła programowania, treść mało ważna) i napotkałem problem, który polega na niepoprawnym działaniu przy wywoływaniu metod, poprzez wskaźnik na klasę która wywodzi się z tej samej klasy bazowej ale dla nich nią nie jest. Problem występuje przy klasach Manager, Fink oraz Highfink, mowa choćby o metodzie SetAll.

//Edit: Uprościłem nieco kod.(głównie main)

#pragma once
#ifndef  emp_h
#define emp_h
#include <iostream>
#include <string>
#include <fstream>
using std::string;
class abstr_emp
{
private:
	string fname;
	string lname;
	string job;
public:
	abstr_emp() :fname(""), lname(""), job("") {};
	abstr_emp(const string & fn, const string & ln,
		const string & j) : fname(fn), lname(ln), job(j) {}
	virtual void ShowAll() const;//opisuje i wyswietla dane
	virtual void SetAll(); //prosi uzytkownika o podanie wartosci
	virtual void writeall(std::ofstream &of);
	virtual ~abstr_emp() = 0 {}
};
class Employee : public abstr_emp
{
public:
	Employee() :abstr_emp("", "", "") {}
	Employee(const string & fn, const string & ln,
		const string & j) : abstr_emp(fn, ln, j) {}
	virtual void  ShowAll() const;
	virtual void SetAll();
	virtual void writeall(std::ofstream &of);
};
class Manager : virtual public abstr_emp
{
private:
	int inchargeof;
protected:
	int InChargeOf() const { return inchargeof; }
	int & InChargeOf() { return inchargeof; }
public:
	Manager() : abstr_emp("", "", ""), inchargeof(0) {}
	Manager(const string & fn, const string & ln,
		const string & j, int ico = 0) : abstr_emp(fn, ln, j), inchargeof(ico) {}
	Manager(const abstr_emp & e, int ico) : abstr_emp(e), inchargeof(ico) {}
	Manager(const Manager & m) : abstr_emp(m), inchargeof(m.inchargeof) {}
	virtual void ShowAll() const;
	virtual void SetAll();
	virtual void writeall(std::ofstream &of);
};
class Fink : virtual public abstr_emp//donosiciel
{
private:
	string reportsto;//do kogo fink(donosiciel) przesyla raport
protected:
	const string ReportsTo() const { return reportsto; }
	string & ReportsTo() { return reportsto; }
public:
	Fink() : abstr_emp("", "", ""), reportsto("") {}
	Fink(const string & fn, const string & ln,
		const string & j, const string & rpo) : abstr_emp(fn, ln, j), reportsto(rpo) {}
	Fink(const abstr_emp & e, const string & rpo) : abstr_emp(e), reportsto(rpo) {}
	Fink(const Fink & e) : abstr_emp(e), reportsto(e.reportsto) {}
	virtual void ShowAll() const;
	virtual void SetAll();
	virtual void writeall(std::ofstream &of);
};
class Highfink : public Manager, public Fink//glowny donosiciel
{
public:
	Highfink() : abstr_emp(), Manager(), Fink() {}
	Highfink(const string & fn, const string & ln,
		const string & j, const string &rpo,
		int ico) : abstr_emp(fn, ln, j), Manager(fn, ln, j, ico), Fink(fn, ln, j, rpo) {}
	Highfink(const abstr_emp & e, const string & rpo, int ico) : abstr_emp(e), Manager(e, ico), Fink(e, rpo) {}
	Highfink(const Fink & f, int ico) : abstr_emp(f), Fink(f), Manager(f, ico) {}
	Highfink(const Manager & m, const string & rpo) : abstr_emp(m), Manager(m), Fink(m, rpo) {}
	Highfink(const Highfink & h) : abstr_emp(h), Fink(h), Manager(h) {}
	virtual void ShowAll() const;
	virtual void SetAll();
	virtual void writeall(std::ofstream &of);
};
#endif // ! emp_h
#include "stdafx.h"
#include <iostream>
#include "emp.h"
using std::cin;
using std::cout;
using std::endl;

void abstr_emp::ShowAll() const
{
	cout << "Imie: " << fname << endl;
	cout << "Nazwisko: " << lname << endl;
	cout << "Praca: " << job << endl;
}

void abstr_emp::SetAll()
{
	cout << "podaj imie: ";
	cin >> fname;
	cout << "podaj nazwisko: ";
	cin >> lname;
	cout << "podaj prace: ";
	cin >> job;
}

void abstr_emp::writeall(std::ofstream & of)
{
	of << fname << endl;
	of << lname << endl;
	of << job << endl;
}
void Employee::ShowAll() const
{
	abstr_emp::ShowAll();
}

void Employee::SetAll()
{
	abstr_emp::SetAll();
}

void Employee::writeall(std::ofstream & of)
{
	of << "4" << endl;
	abstr_emp::writeall(of);
}

void Manager::ShowAll() const
{
	abstr_emp::ShowAll();
	cout << "Ilosc osob za ktore jest odpowiedzialny: " << inchargeof << endl;
}

void Manager::SetAll()
{
	abstr_emp::SetAll();
	cout << "Podaj ilosc osob za ktore jest odpowiedzialny menadzer: ";
	cin >> inchargeof;
}

void Manager::writeall(std::ofstream & of)
{
	of << "1" << endl;
	abstr_emp::writeall(of);
	of << InChargeOf() << endl;
}

void Fink::ShowAll() const
{
	abstr_emp::ShowAll();
	cout << "Nazwa osoby do ktorej jest przesylany raport: " << reportsto << endl;
}

void Fink::SetAll()
{
	abstr_emp::SetAll();
	cout << "Podaj nazwe do kogo jest wysylany raport: ";
	cin >> reportsto;
}

void Fink::writeall(std::ofstream & of)
{
	of << "2" << endl;
	abstr_emp::writeall(of);
	of << ReportsTo() << endl;
}

void Highfink::ShowAll() const
{
	abstr_emp::ShowAll();
	cout << "Ilosc osob za ktore jest odpowiedzialny: " << this->InChargeOf() << endl;
	cout << "Nazwa osoby do ktorej jest przesylany raport: " << this->ReportsTo() << endl;
}

void Highfink::SetAll()
{
	abstr_emp::SetAll();
	cout << "Podaj ilosc osob za ktore jest odpowiedzialny menadzer: ";
	cin >> this->InChargeOf();
	cout << "Podaj nazwe do kogo jest wysylany raport: ";
	cin >> this->ReportsTo();
}

void Highfink::writeall(std::ofstream & of)
{
	of << "3" << endl;
	abstr_emp::writeall(of);
	of << ReportsTo() << endl;
	of << InChargeOf() << endl;
}
// r17z06.cpp: definiuje punkt wejścia dla aplikacji konsolowej.
//

#include "stdafx.h"
#include "emp.h"
#include <iostream>
#include <fstream>
const int MAX = 10;
using namespace std;

int main()
{
	Employee * pc[MAX];
    int how_many_pc = 0;

	while (how_many_pc<10)
	{
		cout << "Wybierz opcje:\n"
			<< "1.Dodanie menadzera\n"
			<< "2.Dodanie donosiciela\n"
			<< "3.Dodanie glownego donosiciela\n"
			<<"4.Dodanie pracownika\n"
			<<"5.Zakoncz"
			<< endl;

		cin >> mode;

		if (mode == 5) break;
		else if ((mode > 4) || (mode < 0))
			continue;
		else if (mode == 1)
		{
			pc[how_many_pc] = dynamic_cast<Employee*>(new Manager);
			pc[how_many_pc]->SetAll();
		}
		else if (mode == 2)
		{
			pc[how_many_pc] = dynamic_cast<Employee*>(new Fink);
			pc[how_many_pc]->SetAll();
		}
		else if (mode == 3)
		{
			pc[how_many_pc] = dynamic_cast<Employee*>(new Highfink);
			pc[how_many_pc]->SetAll();
		}
		else if (mode == 4)
		{
			pc[how_many_pc] = new Employee;
			pc[how_many_pc]->SetAll();
		}
		else
		{
			cout << "Nie ma takiej opcji\n";
		}
		how_many_pc++;
	}
	ofstream fout("Pracownicy.txt");
	for (int i = 0;i < how_many_pc;i++)
	{
		pc[i]->ShowAll();
		pc[i]->writeall(fout);
	}
	fout.close();
	return 0; 
}

 

komentarz 18 lipca 2018 przez Bondrusiek Maniak (61,370 p.)
Wydaje mi się że zbyt dużo wkleiłeś co może nieco zaciemnić ogląd na ten kod i potencjonalną pomoc. Może maksymalnie uprość kod zaznacz gdzie może być błąd wtedy na pewno będzie łatwiej znaleźć rozwiązanie.
komentarz 18 lipca 2018 przez chucksqll Stary wyjadacz (12,930 p.)
Uprościłem main;a. Wydaje mi się, że reszty kodu, a mianowicie emp.h i emp.cpp nie mogę okroić.

2 odpowiedzi

+2 głosów
odpowiedź 18 lipca 2018 przez monika90 Pasjonat (22,940 p.)

dynamic_cast<Employee*>() zawsze zwraca null, ponieważ klasy Manager, Fink i HighFink nie mają z Employee nic wspólnego.

 

A to jest błąd składni:

virtual ~abstr_emp() = 0 {}

jeżeli chcesz zdefiniować ciało czystej funkcji wirtualnej to musisz to zrobić poza klasą:

class abstr_emp
{
public:
    virtual ~abstr_emp() = 0;
};

abstr_emp::~abstr_emp() { }

Wiem, że kompilator Mirosoftu tego nie wymaga, ale standardowe C++ tego wymaga.

komentarz 18 lipca 2018 przez chucksqll Stary wyjadacz (12,930 p.)
To jak w takim razie poradzić sobie z tym rzutowaniem, tak aby to działało?
komentarz 18 lipca 2018 przez monika90 Pasjonat (22,940 p.)
Nie znam treści zadania. Niech klasy Fink i Manager dziedziczą wirtualnie z Employee, albo niech pc to będzie tablica wskaźników do abstr_emp. W żadnym z tych dwóch przypadków rzutowanie nie będzie potrzebne.
+1 głos
odpowiedź 18 lipca 2018 przez Bondrusiek Maniak (61,370 p.)

Witam,

nie wiem jaki jest sens i czy można stosować czysto wirtualny destruktor(ale tu nie chce Cie wprowadzić w błąd, może ktoś inny to zweryfikuje).

    virtual ~abstr_emp(){} // na moim kompilatorze MinGW instrukcja 
// virtual ~abstr_emp(){} zwraca błąd więc to poprawiłem

Co do błędów to szablon dynamic_cast<>() zwraca obiekt rzutowania bądź null w przypadku niepowodzenia więc możesz if'em sprawdzić poprawność rzutowania. W main.cpp

...
        if (mode == 5) break;
        else if ((mode > 4) || (mode < 0))
            continue;
        else if (mode == 1)
        {
            pc[how_many_pc] = dynamic_cast<Employee*>(new Manager);

            if(!pc[how_many_pc])
            {
                std::cout << "Nie dziala rzutowanie z Employee na new Manager\n";
                exit(0);
            }

            pc[how_many_pc]->SetAll();
        }
...

 

Podobne pytania

0 głosów
1 odpowiedź 436 wizyt
0 głosów
1 odpowiedź 683 wizyt
0 głosów
2 odpowiedzi 819 wizyt

92,576 zapytań

141,426 odpowiedzi

319,651 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!

...