Tablica wzkaźników na obiekty

0

Witam
Mam mały problemik z zadaniem 56 (https://sites.google.com/site/pjczaoczne201415/zajecia-8)

Mianowicie przy próbie dodania obiektu do tablicy.

s->add(s1);

chciałem wykorzystać konstruktor kopiujący z Klasy STUDENT. ale coś poszło nie tak.

studenci.cpp

#include "studenci.h"


Studenci::Studenci(int x){
	liczba = 0;
	student = new Student[x];
	
}

	void Studenci::add(Student &A){
		student[liczba].Student(A);
	}

    void Studenci::show(){
    	for(int i = 0; i<liczba;i++)
    		student[i]->show; 
	} 

student.cpp

#include "student.h"
#include <iostream>
#include <cstring>

using namespace std;

		Student::Student::Student(){
			
		}
		Student::Student(char* imie,char* nazwisko,char* PESEL,char* nrIndex,int wiek,int semestr,bool plec){
			this->imie = new char[strlen(imie)+1];
			this->imie = imie; 
			
			this->nazwisko = new char[strlen(nazwisko)+1];
			this->nazwisko = nazwisko;
			
			this->PESEL = new char[strlen(PESEL)+1];
			this->PESEL = PESEL;
			
			this->nrIndex = new char[strlen(nrIndex)+1];
			this->nrIndex = nrIndex;
			
			this->wiek = wiek;
			this->semestr = semestr;
			this->plec = plec;
			
		}
		
		Student::Student (const Student &A){
			
			strcpy(imie,A.imie);
			strcpy(nazwisko,A.nazwisko);
			strcpy(PESEL,A.PESEL);
			strcpy(nrIndex,A.nrIndex);
			wiek = A.wiek;
			semestr = A.semestr;
			plec = A.plec;
			
		}
		
		Student::~Student(){
			
		}
		
		void Student::show(){
			cout<<"Imie i nazwisko : "<<imie<<" "<<nazwisko<<endl;
			cout<<"PESEL : "<<PESEL<<endl;
			cout<<"Nr Index : "<<nrIndex<<endl;
			cout<<"Wiek : "<<wiek<<endl;
			cout<<"Semestr : "<<semestr<<endl;
			if(plec==false)
				cout<<"Plec : Mezczyzna " <<endl;
			else
				cout<<"Plec : Kobieta" <<endl; 
		}
		
		void Student::showDifferences(const Student &A){
			cout<<"Differences\t: Left (this) object \tRight (parameter) object"<<endl;
			cout<<"----------------------------------------------------------------"<<endl;
			
			if (stricmp(imie,A.imie)!=0) 
				cout<<"Imie \t\t: "<<imie<<"\t\t\t"<<A.imie<<endl;		
			if(stricmp(nazwisko,A.nazwisko)!=0)
				cout<<"Nazwisko \t: "<<nazwisko<<"\t\t\t"<<A.nazwisko<<endl;
				
			if(stricmp(PESEL,A.PESEL)!=0)
				cout<<"PESEL \t\t: "<<PESEL<<"\t\t"<<A.PESEL<<endl;
			if(strcmp(nrIndex,A.nrIndex)!=0)
				cout<<"Nr Index \t: "<<nrIndex<<"\t\t\t"<<A.nrIndex<<endl;
			
			if(wiek!=A.wiek)
				cout<<"Wiek \t\t: "<<wiek<<"\t\t\t"<<A.wiek<<endl;
			if(semestr!=A.semestr)
				cout<<"Semestr \t: "<<semestr<<"\t\t\t"<<A.semestr<<endl;
			
			if(plec!=A.plec)
				cout<<"Plec \t\t: "<<plec<<"\t\t\t"<<A.plec<<endl;

A i mam jeszcze jedno pytanko jak destruktor odpowiednio stworzyć w student ? próbowałem czegoś takiego ale niestety nie doszły do poprawnej wersji więc zrezygnowałem

~Student(){
delete []imie;
delete []nazwisko;
delete []PESEL;
delete []nrIndex;
delete wiek;
delete plec;

}
1

Nie chce cię martwić, ale niewiele w tym kodzie jest napisane poprawnie. Właściwie to prawie nic. Serio musisz uzywać char* i nie mozesz std::string?

  1. Klasa powinna sie nazywać "Student" bo przechowuje dane jednego studenta.
  2. Jak użyjesz kontruktora kopiującego Studenta i ten z którego kopiujesz miał krótsze imie to program się wysypie...
  3. Jeśli chodzi o destruktor to delete robisz TYLKO na tym na czym zrobiłeś new. Czy wiek albo płeć były tworzone przez new? Nie. Więc nie wolno ci robić na nich delete.
  4. Twoje "dodawanie" nie ma zupełnie sensu. MUSISZ tam coś PRZYPISAĆ, inaczej nic z tego nie będzie. Ale konstruktor kopiujący tu nie zadziała bo tworząc tablicę od razu stworzyłeś sobie obiekty, więc pozostaje ci operator przypisania tylko (którego nie masz...)
1
Student *s2 = new Student("Arnold", "Smyk", "82736372823", "s1021", 22, 1, true);
Student *s3 = new Student("Arnold", "Smyk", "82736372822", "s1031", 24, 1, false);

// dodanie kopii obiektów klasy Student do kolekcji s
  s->add(s2)->add(s3);

Z tego kawałka kodu wynika, że:

  1. argumentem funkcji add() jest wskaźnik, a nie referencja
  2. ta funkcja powinna coś zwrócić, by można ponownie wywołać add() na wyniku
    Przy czym treść zadania brzmi przechowywał z góra zadaną liczbę wskaźników na obiekty klasy Student. Czyli obiekt klasy Studenci ma tablicę (wektor) wskaźników, a nie obiektów klasy Student.
0

Shalon :
No niestety musi być char :/ na stringach by było znacznie łatwiej...

  1. no tak... mam klasę Student która odpowiada za jedną osobę, no i klasę Studenci która ma odpowiadać za stworzenie tablicy wzkaźników na studentów

  2. Faktycznie nie pomyślałem o tym.
    Zatem w Konstruktorze kopiującym przy każdym atrybucie typu char musiałbym dodać tego typu linijkę ?

 	if(strlen(this.imie)<strlen(A.imie)) this->imie = new char[strlen(A.imie)+1];
  1. Czyli Destruktor to by było tylko tyle ?
~Student(){
delete []imie;
delete []nazwisko;
delete []PESEL;
delete []nrIndex; 

Czyli nie ma możliwości użycia konstruktora ?
Czyli proponujesz przeciążenie operatora "=" tak ?

0
ice25 napisał(a):

Zatem w Konstruktorze kopiującym przy każdym atrybucie typu char musiałbym dodać tego typu linijkę ?

 	if(strlen(this.imie)<strlen(A.imie)) this->imie = new char[strlen(A.imie)+1];

I miałbyś piękny wyciek pamięci. Najpierw musisz usunąć starą pamięć.

  1. Czyli Destruktor to by było tylko tyle ?
~Student(){
delete []imie;
delete []nazwisko;
delete []PESEL;
delete []nrIndex; 

Tak.

Czyli nie ma możliwości użycia konstruktora ?
Czyli proponujesz przeciążenie operatora "=" tak ?
Nie, bo jeśli zgodnie z treścią zadania trzymasz wskaźniki, a przy dodaniu tworzysz kopie, to coś takiego wystarczy:

Studenci* Studenci::add(Student* s)
{
    studenci[liczba++] = new Student(*s);
    return this;
}

Tylko potem przy sprzątaniu trzeba pamiętać o usuwaniu wszystkich studentów przed delete[] studenci;

0
  1. to juz wiem dlaczego stosuje się string :) dużo mniej kodu :p
  2. Jeśli tworzę destruktor wówczas nie będę mógł powołać do życia obiektu w taki sposób tak ?
Student s1("Adam", "Smyk", "82736372821", "s1020", 22, 1, false);
  1. gdybyś wyjaśnił czemu metoda add jest "Studenci * " ... bo troszkę tego nie łapie.
    Czemu nie może być typu void ?

no i wyskakuje niestety błąd

12 23 [Error] no match for 'operator=' (operand types are 'Student' and 'Student*')
studenci.cpp

#include "studenci.h"


Studenci::Studenci(int x){
	liczba = 0;
	student = new Student[x];
	
}

	Studenci* Studenci::add(Student* s)
{
    student[liczba++] = new Student(*s);
    return this;
}

    void Studenci::show(){
    	for(int i = 0; i<liczba;i++)
    		student[i].show();
		
	}

student.cpp

#include "student.h"
#include <iostream>
#include <cstring>

using namespace std;

		Student::Student::Student(){
			
		}
		Student::Student(char* imie,char* nazwisko,char* PESEL,char* nrIndex,int wiek,int semestr,bool plec){
			this->imie = new char[strlen(imie)+1];
			this->imie = imie; 
			
			this->nazwisko = new char[strlen(nazwisko)+1];
			this->nazwisko = nazwisko;
			
			this->PESEL = new char[strlen(PESEL)+1];
			this->PESEL = PESEL;
			
			this->nrIndex = new char[strlen(nrIndex)+1];
			this->nrIndex = nrIndex;
			
			this->wiek = wiek;
			this->semestr = semestr;
			this->plec = plec;
			
		}
		
		Student::Student (const Student &A){
			if(strlen(this->imie)<strlen(A.imie)) this->imie = new char[strlen(A.imie)+1];	
			strcpy(imie,A.imie);
			if(strlen(this->nazwisko)<strlen(A.nazwisko)) this->imie = new char[strlen(A.nazwisko)+1];	
			strcpy(nazwisko,A.nazwisko);
			if(strlen(this->PESEL)<strlen(A.PESEL)) this->imie = new char[strlen(A.PESEL)+1];	
			strcpy(PESEL,A.PESEL);
			if(strlen(this->nrIndex)<strlen(A.nrIndex)) this->imie = new char[strlen(A.nrIndex)+1];	
			strcpy(nrIndex,A.nrIndex);
			wiek = A.wiek;
			semestr = A.semestr;
			plec = A.plec;
			
		}
		
		Student::~Student(){
			delete[]imie;
			delete[]nazwisko;
			delete []PESEL;
			delete []nrIndex;
		}
		
		void Student::show(){
			cout<<"Imie i nazwisko : "<<imie<<" "<<nazwisko<<endl;
			cout<<"PESEL : "<<PESEL<<endl;
			cout<<"Nr Index : "<<nrIndex<<endl;
			cout<<"Wiek : "<<wiek<<endl;
			cout<<"Semestr : "<<semestr<<endl;
			if(plec==false)
				cout<<"Plec : Mezczyzna " <<endl;
			else
				cout<<"Plec : Kobieta" <<endl; 
		}
		
		void Student::showDifferences(const Student &A){
			cout<<"Differences\t: Left (this) object \tRight (parameter) object"<<endl;
			cout<<"----------------------------------------------------------------"<<endl;
			
			if (stricmp(imie,A.imie)!=0) 
				cout<<"Imie \t\t: "<<imie<<"\t\t\t"<<A.imie<<endl;		
			if(stricmp(nazwisko,A.nazwisko)!=0)
				cout<<"Nazwisko \t: "<<nazwisko<<"\t\t\t"<<A.nazwisko<<endl;
				
			if(stricmp(PESEL,A.PESEL)!=0)
				cout<<"PESEL \t\t: "<<PESEL<<"\t\t"<<A.PESEL<<endl;
			if(strcmp(nrIndex,A.nrIndex)!=0)
				cout<<"Nr Index \t: "<<nrIndex<<"\t\t\t"<<A.nrIndex<<endl;
			
			if(wiek!=A.wiek)
				cout<<"Wiek \t\t: "<<wiek<<"\t\t\t"<<A.wiek<<endl;
			if(semestr!=A.semestr)
				cout<<"Semestr \t: "<<semestr<<"\t\t\t"<<A.semestr<<endl;
			
			if(plec!=A.plec)
				cout<<"Plec \t\t: "<<plec<<"\t\t\t"<<A.plec<<endl;
}
0

nikt nie pomoże ?

0

Ad 3. Chrzan totalny, dla tego nikt nie chce odpowiadać.
Ad 4. Aby można było dodawać serię jak tu: http://4programmers.net/Forum/1099639
Ad 5. Napis musisz przekopiować za pomocą strcpy albo zamiast new+strcpy użyj strdup lub sam go napisz.

0

Ja to bym w ogóle zregzygnował z dynamicznej alokacji w przypadku imiona, nazwiska i nr. pesel. Rzadko kiedy imię przekracza 16 znaków, dla nazwiska 32 znaki to świat z głową. PESEL z kolei ma zawsze tyle samo cyfr - wszystko to lepiej machnąć na sztywno i nie bawić się w mikroskopijne alokacje :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1