[C++] Problem z konstruktorem kopiowania

Witam. Moim zadaniem jest napisanie programu, który wczytuje od użytkownika studentów i pracowników uczelni po czym gdy użytkownik zakończy działanie programu uzyska wynik wpisanych danych. Problem mój tkwi w konstruktorze kopiowania i właściwie nie wiem czego dotyczy dlatego prosiłbym o pomoc w jego rozwiązaniu.

Pod koniec kodu, zaznaczyłem komentarzami miejsca wyrzucania błędu przez kompilator.

#include

#include


using namespace std;


/* ======== KLASA BAZOWA ======== */

class baza

{

protected:

	char *imie;

	char *nazwisko;

	char *email;

public:

	baza() : imie("asd"), nazwisko("asd"), email("asdad@wp.pl"){};

	baza(char *a, char *b, char *c) : imie(a), nazwisko(b), email(c){};

	baza(baza &dane) : imie(dane.imie), nazwisko(dane.nazwisko), email(dane.email){};


	virtual void wypisz()

	{

		cout<<"Imie: "<
		cout<<"Nazwisko: "<
		cout<<"Email: "<
	}

};

/* ============================== */


/* ======== KLASA POCHODNA - STUDENCI ======== */

class studenci : public baza // klasa pochodna

{

protected:

	int nr_indeksu;

	int rok_studiow;

public:

	studenci(char *a, char *b, char *c) : baza(a,b,c) // konstruktor domyslny

	{

		imie = a;

		nazwisko = b;

		email = c;

		nr_indeksu = 0;

		rok_studiow = 0;

	}

	studenci(int d, int e, char *a, char *b, char *c) : baza(a,b,c) // konstruktor z parametrami

	{

		imie = a;

		nazwisko = b;

		email = c;

		nr_indeksu = d;

		rok_studiow = e;

	}

	studenci(studenci &dane, char *a, char *b, char *c) : baza(a,b,c) // konstruktor kopiujacy

	{

		imie = a;

		nazwisko = b;

		email = c;

		nr_indeksu = dane.nr_indeksu;

		rok_studiow = dane.rok_studiow;

	}


	void wypisz()

	{

		cout<<"Imie: "<
		cout<<"Nazwisko: "<
		cout<<"Email: "<
		cout<<"Nr indeksu: "<
		cout<<"Rok studiow: "<
	}

};

/* ============================================ */


/* ======== KLASA POCHODNA - PRACOWNICY ======= */

class pracownicy : public baza

{

protected:

	int prowadzone_przedmioty;

	int grupy_studenckie;

	int liczba_magistrantow;

public:

	pracownicy(char *a, char *b, char *c) : baza(a,b,c) // konstruktor domyslny

	{

		imie = a;

		nazwisko = b;

		email = c;

		prowadzone_przedmioty = 0;

		grupy_studenckie = 0;

		liczba_magistrantow = 0;

	}


	pracownicy(int f, int g, int h, char *a, char *b, char *c) : baza(a,b,c) // konstruktor z parametrami

	{

		imie = a;

		nazwisko = b;

		email = c;

		prowadzone_przedmioty = f;

		grupy_studenckie = g;

		liczba_magistrantow = h;

	}


	pracownicy(pracownicy &dane, char *a, char *b, char *c) : baza(a,b,c) // konstruktor kopiujacy

	{

		imie = a;

		nazwisko = b;

		email = c;

		prowadzone_przedmioty = dane.prowadzone_przedmioty;

		grupy_studenckie = dane.grupy_studenckie;

		liczba_magistrantow = dane.liczba_magistrantow;

	}


	void wypisz()

	{

		cout<<"Imie: "<
		cout<<"Nazwisko: "<
		cout<<"Email: "<
		cout<<"Prowadzone przedmioty: "<
		cout<<"Grupy studenckie: "<
		cout<<"Liczba magistrantow: "<
	}

};

/* ============================================ */


/* ======== ZMIENNE GLOBALNE ======== */

baza *tablica1[50];

studenci *tablica2[50];

pracownicy *tablica3[50];

char a[50],b[50],c[50];

int d,e,f,g,h,i;

int liczba_dodan_p=0, liczba_dodan_s=0;

/* ================================== */


/* ======== MAIN ======== */

int main()

{	

	int wybor;

	char wybor2;

powrot:

	cout<<"Witaj w bazie pracownikow i studentow!"<
	cout<<"Co chcesz teraz zrobic?"<
	cout<<"1. Dodac pracownika"<
	cout<<"2. Dodac studenta"<
	cout<<"3. Wypisac dane i zakonczyc program"<
	cout<<"Wybor: ";

	cin>>wybor;


	if(wybor==1)

	{		

		for(i=0; i<50 ; i++)

		{

			system("CLS");

			cout<<"Podaj imie: ";

			cin>>a;

			cout<<"Podaj nazwisko: ";

			cin>>b;

			cout<<"Podaj email: ";

			cin>>c;

			cout<<"Prowadzone przedmioty: ";

			cin>>f;

			cout<<"Grupy studenckie: ";

			cin>>g;

			cout<<"Liczba magistrantow: ";

			cin>>h;

			cout<

			tablica3[i] = new pracownicy(f, g, h, a, b, c);

			liczba_dodan_p++; // sumuje liczbe wpisanych pracownikow


			cout<<"Chcesz kontynuuowac dodawanie pracownika? [t/n]: ";

			cin>>wybor2;


			if(wybor2=='n')

			{

				system("CLS");

				goto powrot;

			}

		}

	}


	if(wybor==2)

	{		

		for(i=0; i<50 ; i++)

		{

			system("CLS");

			cout<<"Podaj imie: ";

			cin>>a;

			cout<<"Podaj nazwisko: ";

			cin>>b;

			cout<<"Podaj email: ";

			cin>>c;

			cout<<"Nr indeksu: ";

			cin>>d;

			cout<<"Rok studiow: ";

			cin>>e;

			cout<

			tablica2[i] = new studenci(d, e, a, b, c);

			liczba_dodan_s++; // sumuje liczbe wpisanych osob


			cout<<"Chcesz kontynuuowac dodawanie pracownika? [t/n]: ";

			cin>>wybor2;


			if(wybor2=='n')

			{

				system("CLS");

				goto powrot;

			}

		}

	}


	if(wybor==3)

	{

		studenci obiekt1(tablica2, a,b,c); // <--- TUTAJ WYRZUCA BLAD

		pracownicy obiekt2(tablica3, a,b,c); // <--- TUTAJ WYRZUCA BLAD


		baza *wsk;


		wsk=&obiekt1;

		wsk->wypisz();

		wsk=&obiekt2;

		wsk->wypisz();


		exit(0);

	}


	return 0;

}

/* ====================== */

W wyróżnionych miejscach podajesz tablicę wskaźników do konstruktora, który przyjmuje referencję na obiekt. Zapewne chciałeś podawać elementy tej tablicy - czyli np. w pętli po zmiennej i: *tablica2_._

Dodatkowo kod jest zły pod paroma względami:

1) Użycie char* do przechowywania tekstu - oczywiście można to zrobić, ale przez zwyczajne kopiowanie wskaźników to prędzej lub później nie zadziała tak jak chcesz. Prościej użyć std::string.

2) stdlib.h -> cstdlib, skoro to C++

3) Nazywanie zmiennych kolejnymi literami alfabetu nie jest zbyt czytelne. Ogólnie nazywanie zmiennych zgodnie z ich przeznaczeniem/tym co robią nie jest głupie.

4) Te fragmenty kodu, które komentujesz jako “konstruktor kopiujący”, nie są nimi. Zobacz http://en.wikipedia.org/wiki/Copy_constructor . Zbędne są te dodatkowe parametry a,b,c.

5) goto w 99% przypadków nie jest zalecany, to samo zrobisz pętlą do-while.

Dzięki @nr47 za pomoc + wskazówki do tego jak następnym razem nie pisać programu - bardzo mi się przydały :slight_smile:

class baza{
#include

#include

#include


using namespace std;


/* ======== KLASA BAZOWA ======== */

class baza

{

protected:

	string imie;

	string nazwisko;

	string email;

public:

	baza() : imie("asd"), nazwisko("asd"), email("asdad@wp.pl"){};

	baza(string a, string b, string c) : imie(a), nazwisko(b), email(c){};

	baza(baza &dane) : imie(dane.imie), nazwisko(dane.nazwisko), email(dane.email){};


	virtual void wypisz()

	{

		cout<<"Imie: "<
		cout<<"Nazwisko: "<
		cout<<"Email: "<
	}

};

/* ============================== */


/* ======== KLASA POCHODNA - STUDENCI ======== */

class studenci : public baza // klasa pochodna

{

protected:

	int nr_indeksu;

	int rok_studiow;

public:

	studenci(string a, string b, string c) // konstruktor domyslny

	{

		imie = a;

		nazwisko = b;

		email = c;

		nr_indeksu = 0;

		rok_studiow = 0;

	}

	studenci(int d, int e, string a, string b, string c) // konstruktor z parametrami

	{

		imie = a;

		nazwisko = b;

		email = c;

		nr_indeksu = d;

		rok_studiow = e;

	}

	studenci(studenci &dane, string a, string b, string c) // konstruktor kopiujacy

	{

		imie = a;

		nazwisko = b;

		email = c;

		nr_indeksu = dane.nr_indeksu;

		rok_studiow = dane.rok_studiow;

	}


	void wypisz()

	{

		cout<<"Imie: "<
		cout<<"Nazwisko: "<
		cout<<"Email: "<
		cout<<"Nr indeksu: "<
		cout<<"Rok studiow: "<
	}

};

/* ============================================ */


/* ======== KLASA POCHODNA - PRACOWNICY ======= */

class pracownicy : public baza

{

protected:

	int prowadzone_przedmioty;

	int grupy_studenckie;

	int liczba_magistrantow;

public:

	pracownicy(string a, string b, string c) // konstruktor domyslny

	{

		imie = a;

		nazwisko = b;

		email = c;

		prowadzone_przedmioty = 0;

		grupy_studenckie = 0;

		liczba_magistrantow = 0;

	}


	pracownicy(int f, int g, int h, string a, string b, string c) // konstruktor z parametrami

	{

		imie = a;

		nazwisko = b;

		email = c;

		prowadzone_przedmioty = f;

		grupy_studenckie = g;

		liczba_magistrantow = h;

	}


	pracownicy(pracownicy &dane, string a, string b, string c) // konstruktor kopiujacy

	{

		imie = a;

		nazwisko = b;

		email = c;

		prowadzone_przedmioty = dane.prowadzone_przedmioty;

		grupy_studenckie = dane.grupy_studenckie;

		liczba_magistrantow = dane.liczba_magistrantow;

	}


	void wypisz()

	{

		cout<<"Imie: "<
		cout<<"Nazwisko: "<
		cout<<"Email: "<
		cout<<"Prowadzone przedmioty: "<
		cout<<"Grupy studenckie: "<
		cout<<"Liczba magistrantow: "<
	}

};

/* ============================================ */


/* ======== ZMIENNE GLOBALNE ======== */

baza *tablica1[50];

studenci *tablica2[50];

pracownicy *tablica3[50];

string a,b,c;

int d,e,f,g,h,i;

int liczba_dodan_p=0, liczba_dodan_s=0;

/* ================================== */


/* ======== MAIN ======== */

int main()

{	

	int wybor;

	char wybor2;

powrot:

	cout<<"Witaj w bazie pracownikow i studentow!"<
	cout<<"Co chcesz teraz zrobic?"<
	cout<<"1. Dodac pracownika"<
	cout<<"2. Dodac studenta"<
	cout<<"3. Wypisac dane i zakonczyc program"<
	cout<<"4. Modyfikowac dane"<
	cout<<"Wybor: ";

	cin>>wybor;


	if(wybor==1)

	{		

		for(i=0; i<50 ; i++)

		{

			system("CLS");

			cout<<"Podaj imie: ";

			cin>>a;

			cout<<"Podaj nazwisko: ";

			cin>>b;

			cout<<"Podaj email: ";

			cin>>c;

			cout<<"Prowadzone przedmioty: ";

			cin>>f;

			cout<<"Grupy studenckie: ";

			cin>>g;

			cout<<"Liczba magistrantow: ";

			cin>>h;

			cout<

			tablica3[i] = new pracownicy(f, g, h, a, b, c);

			liczba_dodan_p++; // sumuje liczbe wpisanych pracownikow


			cout<<"Chcesz kontynuuowac dodawanie pracownika? [t/n]: ";

			cin>>wybor2;


			if(wybor2=='n')

			{

				system("CLS");

				goto powrot;

			}

		}

	}


	if(wybor==2)

	{		

		for(i=0; i<50 ; i++)

		{

			system("CLS");

			cout<<"Podaj imie: ";

			cin>>a;

			cout<<"Podaj nazwisko: ";

			cin>>b;

			cout<<"Podaj email: ";

			cin>>c;

			cout<<"Nr indeksu: ";

			cin>>d;

			cout<<"Rok studiow: ";

			cin>>e;

			cout<

			tablica2[i] = new studenci(d, e, a, b, c);

			liczba_dodan_s++; // sumuje liczbe wpisanych osob


			cout<<"Chcesz kontynuuowac dodawanie pracownika? [t/n]: ";

			cin>>wybor2;


			if(wybor2=='n')

			{

				system("CLS");

				goto powrot;

			}

		}

	}


	if(wybor==3)

	{

		system("CLS");

		baza *wsk;

		cout<<"PRACOWNICY:"<
		for(i=0; i
		{

			pracownicy obiekt2(*tablica3[i]);

			wsk=&obiekt2;

			wsk->wypisz();

		}


		cout<<"STUDENCI:"<
		for(i=0; i
		{

			studenci obiekt1(*tablica2[i]);

			wsk=&obiekt1;

			wsk->wypisz();

		}		


		exit(0);

	}


	if(wybor==4)

	{

		system("CLS");

		cout<<"Ktore dane chcesz modyfikowac?"<
		cout<<"1. Pracownicy"<
		cout<<"2. Studenci"<
		cout<<"Wybor: ";

		cin>>wybor;


		if(wybor==1)

		{

			for(i=0; i<50 ; i++)

			{

				system("CLS");

				cout<<"Podaj imie: ";

				cin>>a;

				cout<<"Podaj nazwisko: ";

				cin>>b;

				cout<<"Podaj email: ";

				cin>>c;

				cout<<"Prowadzone przedmioty: ";

				cin>>f;

				cout<<"Grupy studenckie: ";

				cin>>g;

				cout<<"Liczba magistrantow: ";

				cin>>h;

				cout<

				tablica3[i] = new pracownicy(f, g, h, a, b, c);

				liczba_dodan_p++; // sumuje liczbe wpisanych pracownikow


				cout<<"Chcesz kontynuuowac dodawanie pracownika? [t/n]: ";

				cin>>wybor2;


				if(wybor2=='n')

				{

					system("CLS");

					goto powrot;

				}

			}

		}


		if(wybor==2)

		{

			for(i=0; i<50 ; i++)

			{

				system("CLS");

				cout<<"Podaj imie: ";

				cin>>a;

				cout<<"Podaj nazwisko: ";

				cin>>b;

				cout<<"Podaj email: ";

				cin>>c;

				cout<<"Nr indeksu: ";

				cin>>d;

				cout<<"Rok studiow: ";

				cin>>e;

				cout<

				tablica2[i] = new studenci(d, e, a, b, c);

				liczba_dodan_s++; // sumuje liczbe wpisanych osob


				cout<<"Chcesz kontynuuowac dodawanie pracownika? [t/n]: ";

				cin>>wybor2;


				if(wybor2=='n')

				{

					system("CLS");

					goto powrot;

				}

			}

		}

	}


	return 0;

}

/* ====================== */

Zrobiłem to w ten sposób i wszystko działa idealnie :slight_smile: Potrzebuję tylko destruktora, który rekurencyjnie wywołuje czynność usuwania obiektu wskazywanego przez wskaźnik do następnego elementu listy. Proszę o pomoc.

Zamiast destruktora, potrzebujesz po prostu zwalniać pamięć, którą przydzielasz i wpisujesz do tablic tablica{1,2,3}. W związku z tym, że nie zwalniasz pamięci (delete), trudno powiedzieć, aby wszystko działało idealnie, co najwyżej po działaniu trudno powiedzieć, że coś jest nie tak.

Jeszcze raz, moje uwagi:

  1. Logiczne nazywanie zmiennych, zgodnie z tym co przechowują (w większośći przypadków a, b, c, d, e, f, g, h, tablica1, tablica2, tablica3 to niezbyt dobre nazwy)

  2. Klasa studenci i pracownicy: to co komentujesz jako konstruktor domyślny nie jest kosntruktorem domyślnym, to co komentujesz jako konstruktor kopiujący nie jest konstruktorem kopiującym

  3. Masz powtarzające się duże kawałki kodu, czemu nie przenieść ich do funkcji (wybor == 2, wybor == 3)

  4. Z tego co widzę wystarczy Ci jedna tablica, przechowująca wskaźniki na baza.

  5. Jeśli już masz tablice wskaźników i wpisujesz do nich wskaźniki na dynamicznie zaalokowaną pamięć, trzeba tę pamięć zwalniać. Najpierw wpisałbym do tablicy same NULL-e, następnie przy dodawaniu elementu sprawdzał czy na danej pozycji jest NULL czy nie. Jeśli nie, najpierw usunąć stary, potem dodać nowy.

Czemu klasę reprezentującą jednego studenta nazywasz “studenci”?

Kilka drobnych poprawek w klasie baza, i fundamentalne poprawki w klasie student:

/* ======== KLASA BAZOWA ======== */

class baza

{

protected:

   string imie;

   string nazwisko;

   string email;

public:

   baza() : imie("asd"), nazwisko("asd"), email("asdad@wp.pl") {}

   baza(const string& a, const string& b, const string& c) : imie(a), nazwisko(b), email(c) {}

   baza(const baza &dane) : imie(dane.imie), nazwisko(dane.nazwisko), email(dane.email) {}

};


/* ======== KLASA POCHODNA - STUDENCI ======== */

class student : public baza // klasa pochodna

{

protected:

	int nr_indeksu;

	int rok_studiow;

public:

	student() : baza(), nr_indeksu(0), rok_studiow(0) {} // konstruktor domyslny

	student(int d, int e, string a, string b, string c) : baza(a,b,c), nr_indeksu(d), rok_studiow(e) {} // konstruktor z parametrami

	student(const student &dane) : baza(dane /*automatyczne rzutowanie na typ bazowy*/), nr_indeksu(dane.nr_indeksu), rok_studiow(dane.rok_studiow) {} // konstruktor kopiujacy

};

Praca domowa: popraw analogicznie klasę pracownik.