Przeciążenia operatorów dla klas

0

Cześć wszystkim ;).
Mam program, a w nim dwie klasy - w zasadzie identyczne - w obu konstruktor tworzy tablicę dynamiczną o zadanym przez użytkownika rozmiarze, z tym, że pierwsza (Tablica) tworzy obiekty przechowujące w tablicy elementy typu int, a druga (TablicaD) obiekty z tablicami liczb typu double. Za zadanie mam teraz dodać przeciążenia operatorów +,-,*,/ jako operacje od odpowiadających sobie elementach dwóch obiektów danej klasy oraz przeciążenie operatorów >> i << na potrzeby funkcji cin i cout. Jak coś takiego zrobić ? Naczytałem się w necie, aczkolwiek nie ma nigdzie tego wyjaśnionego w przystępny sposób, a na czytanie 100 stron Symfonii Grębosza średnio mam teraz czas, bo program muszę oddać jutro. Jeżeli ktoś mógłby to jakoś po krótce wytłumaczyć i napisać mi coś takiego, będę wdzięczny.
Załączam ciało klasy (tej z double, klasa z intami wygląda analogicznie):
TablicaD.h:

class TablicaD  // klasa z tablica liczb typu DOUBLE
{
private:
	int licznik;       // deklaracja licznika elementow tablicy
	int rozmiar;	   // deklaracja zmiennej uzywana jako rozmiar tablicy dynamicznej
	double *wtab;         // deklaracja wskaznika do utworzenia tablcy dynamicznej
	
	
	
public:
	TablicaD(int n);				  // deklaracja konstruktora
	~TablicaD();					  // deklaracja destruktora
	static int liczba_tablic;     // zmienna statyczna, zawierajaca informacje o ilosci utworzonych obiektow klasy Tablica

//==================================================================================================
//                   FUNKCJE SKLADOWE
	int size();
	int ile_tablic();
	void wypelnij();
	void wyswietl();																			 
	void zeruj();									 											  
	void zapis_do_pliku();	

		//funkcje sortujace
	void sortuj_m();																			  
	void sortuj_r();

		//funkcje zmienajace notacje
	void szesnastkowo();
	void naukowo();
	void osemkowo();

	//funkcja kontrolujaca prezycje
	void precyzja(int pr);
//==================================================================================================
	
	
};


TablicaD.cpp:

#include "TablicaD.h"
#include "naglowek.h"

int TablicaD::liczba_tablic;   // definicja zmiennej statycznej (domyslnie inicjalizowana zerem)

TablicaD::TablicaD(int n)       // definicja funkcji konstruktora
{
	
	rozmiar = n;
	wtab = new double[rozmiar];		// dynamiczna alokacja tablicy
	cout << "Zostala utworzona tablica elementow double o rozmiarze: " << rozmiar << endl;
	liczba_tablic++;
}


TablicaD::~TablicaD(void)		 // definicja funkcji destruktora
{
	cout << "Destruktor usuwa obiekt /n";
	delete wtab;
	liczba_tablic--;
	
}

////////////////////////////////////////////////////////////////////////////////////////////////
//                          DEFINICJE FUNKCJI SKLADOWYCH
void TablicaD::wypelnij()      // funkcja wypelniajaca elementy tablicy
{
	for(int i=0; i<rozmiar; i++)
	{
		cout << "Podaj element nr " << i+1 << ": ";
		cin >> wtab[i];   // wypelnianie tablicy z kontrola precyzji wprowadzania do 3 miejsc po przecinku
		cout << endl;
		licznik++;
	}
}

void TablicaD::wyswietl()	   // funkcja wyswietlajaca zawartosc tablicy
{
	cout << "Aktualna zawartosc tablicy: " << endl;
	for(int i=0; i<rozmiar; i++)
	{
		cout << "Element " << i+1 << ". : "  << wtab[i] << endl;
	}
}

int TablicaD::size()		// funkcja zwracajaca jako wartosc liczbe elementow tablicy
{
	return rozmiar;
}

int TablicaD::ile_tablic()		// funkcja zwracajaca jako wartosc zmienna statyczna bedaca iloscia utworzonych obiektow
{
	return liczba_tablic;
}


void TablicaD::zeruj()		// funkcja zerujaca elementy tablicy
{
	cout << "\nTeraz nastapi zerowanie tablicy.\n";
	for(int i=0; i<rozmiar; i++)
	{
		wtab[i]=0;
	}

	wyswietl();
}

void TablicaD::zapis_do_pliku()		// funkcja zapisujaca strumieniowo zawartosc tablicy do pliku tablica.txt
{
	//zapis zawartosci tablicy do pliku
	ofstream plik;	
	plik.open("tablica.txt");
	plik << "Zawartosc tablicy: \n";
	for(int i=0; i<rozmiar; i++)
	{
		plik << wtab[i] << " ";
		
	}
	plik.close();
	
}

void TablicaD::sortuj_m()		// sortowanie elementow tablicy malejaco metoda babelkowa
{
	for(int j=0; j<rozmiar; j++)
	for(int i=0; i<rozmiar-1; i++)
	{
		if(wtab[i] < wtab[i+1]) 
		{
			int temp = wtab[i]; wtab[i] = wtab[i+1]; wtab[i+1] = temp;
		}
	}
		cout << "\n Po sortowaniu.\n";
		wyswietl();
}

void TablicaD::sortuj_r()		// sortowanie elementow tablicy rosnaco metoda babelkowa
{
	for(int j=0; j<rozmiar-1; j++)
	for(int i=0; i<rozmiar-1; i++)
	{
		if(wtab[i] > wtab[i+1]) 
		{
			int temp = wtab[i]; wtab[i] = wtab[i+1]; wtab[i+1] = temp;
		}
	}
	cout << "\n Po sortowaniu.\n";
	wyswietl();
		
}

void TablicaD::szesnastkowo()
{
	for(int i=0; i<rozmiar; i++)
	{
		cout << "Element " << i+1 << ". : " << hex << wtab[i] << endl;
	}
}

void TablicaD::naukowo()
{
	for(int i=0; i<rozmiar; i++)
	{
		cout << "Element " << i+1 << ". : " << scientific << wtab[i] << endl;
	}
}

void TablicaD::osemkowo()
{
	
	for(int i=0; i<rozmiar; i++)
	{
		cout << "Element " << i+1 << ". : " << oct << wtab[i] << endl;

	}
}

void TablicaD::precyzja(int pr)
{
	cout << "Aktualna zawartosc tablicy po kontroli precyzji: " << endl;
	for(int i=0; i<rozmiar; i++)
	{
		cout << "Element " << i+1 << ". : " << setprecision(pr+1) << wtab[i] << endl;
	}

}
/////////////////////////////////////////////////////////////////////////////////////////////
0

Mam program, a w nim dwie klasy - w zasadzie identyczne - w obu konstruktor tworzy tablicę dynamiczną o zadanym przez użytkownika rozmiarze, z tym, że pierwsza (Tablica) tworzy obiekty przechowujące w tablicy elementy typu int, a druga (TablicaD) obiekty z tablicami liczb typu double.

ŹLE.
http://www.cplusplus.com/doc/tutorial/templates/

0

Co źle? Wszystko działa i ma tak zostać.

0

Masz dwie klasy robiące dokładnie to samo, a jedynie jedna z nich opiera się na intach, a druga na double, tak?
Dlaczego więc po ludzku nie skorzystasz z typów generycznych (template), tylko łamiesz zasadę DRY?

0

Dlaczego więc po ludzku nie skorzystasz z typów generycznych
Bo jeszcze nie umie. Spokojnie, na razie skupmy się na operatorach...

class TablicaD  // klasa z tablica liczb typu DOUBLE
{
   ....
   // operator wykonujący działanie typu TablicaD = TablicaD+TablicaD
   TablicaD operator+(const TablicaD &other) const;
};

TablicaD TablicaD::operator+(const TablicaD &other) const
{
   // dodać 'this' i 'other' wg. zadanego algorytmu i zwrócić wynik
}
0

Tak, właśnie dlatego, że jeszcze nie umiem, a po drugie z tego względu, że to zadany projekt na laboratoria i tak mam w poleceniu.
Czyli jak na tym konkretnym przykładzie wykonać np. przeładowanie operatora dodawania + ? Z tego, co rozumiem, ma on wykonywać np. działanie obiekt1.TablicaD + obiekt2.TablicaD i jako wynik zwracać nową tablicę (?) z liczbami będącymi sumami kolejnych elementów tablic zawartych w obiekt1 i obiekt2.

0

Próbowałem jakoś to napisać, operator + ma sumować dwa obiekty typu TablicaD, czyli w tym przypadku sumować poszczególne elementy tablicy zawartej w obiekcie przykładowo Obiekt1 i Obiekt2.
Wrzucam na nowo treść (dwa pliki) mojej klasy, bo teraz pracuję już tylko na jednej klasie (TablicaD).
TablicaD.h -> http://4programmers.net/Pastebin/2163
TablicaD.cpp -> http://4programmers.net/Pastebin/2164 (na samym dole jest moja próba przeciążenia operatora +)
Plik nagłówkowy naglowek.h -> http://4programmers.net/Pastebin/2165

Nie wiem, czy to przeładowanie operatora dodawania zrobione jest dobrze. Dałem po prostu alokację nowej tablicy, i sumowanie poszczególnych elementów tablic z Obiekt1 i Obiekt2 i zapis ich do tej nowej tablicy na poszczególnych pozycjach. Nie wiem jednak, co ta funkcja przeciążająca ma zwracać (jest to ujęte w komentarze).

W programie głównym to sumowanie dwóch obiektów klasy TablicaD zapisałem następująco:

TablicaD obiekt2(5);
	TablicaD suma(5);
	suma = obiekt + obiekt2;
	cout << "\n\nSuma wynosi: \n";
	suma.wyswietl();

Jeśli ktoś jest w stanie pomóc, będę wdzięczny.

0

Tak na logikę, to funkcja przeciążająca operator powinna zwracać obiekt typu TablicaD, nie sądzisz?

0

hmm, w tym znaczeniu, że powinna zwracać NOWY obiekt typu TablicaD ?
W takim razie jak mam to wykonać, żeby tak jak jest, elementy tablicy były sumowane (wydaje mi się, że sumowanie jest poprawne) i następnie został zwrócony nowy obiekt typu TablicaD, który będzie zawierał tę nowo utworzoną tablicę ? I jak to odebrać w funkcji main, żeby później móc wywołać funkcję (przykładowo NowyObiekt to ten zwracany obiekt typu TablicaD) NowyObiekt.wyswietl() albo jakoś inaczej tę sumę (tzn. w zasadzie tablicę sum) wyświetlić ?

0

Coś w tym guście:

TablicaD TablicaD::operator+(const TablicaD &other) const
{
	double *t = new double[rozmiar];

	for(int i=0; i<rozmiar; i++)
	{
		t[i] = this->wtab[i] + other.wtab[i];
	}
	
              TablicaD *nowy_obiekt = new TablicaD();
              nowy_obiekt->wtab = t;
              return nowy_obiekt;
}

Btw, other to liczba mnoga afair :P

0

Wyrzuca błąd, jak tak to napisałem, jak poleciłeś:

No instance of constructor "TablicaD::TablicaD" matches the argument list.
No suitable constructor exists to convert from "TablicaD *" to "TablicaD" 
0

Napisałem "coś w tym guście".
Musiałbyś więc:
1.TablicaD nowy_obiekt = new TablicaD(0);
albo
2.Przeciążyć konstruktor klasy TablicaD tak, aby istniała jego bezparametrowa wersja.

0

Ok, teraz przeciążenie wygląda tak:

TablicaD* TablicaD::operator+(const TablicaD &other) const
{
        double *t = new double[rozmiar];
 
        for(int i=0; i<rozmiar; i++)
        {
                t[i] = this->wtab[i] + other.wtab[i];
        }
 
              TablicaD *nowy_obiekt = new TablicaD(0);
              nowy_obiekt->wtab = t;
              return nowy_obiekt;
}

Okej, wszystko fajnie działa, zwraca ten nowy_obiekt, ale do czego to jest zwracane ? Jak mam teraz np. mając dwa obiekty - np. obiekt i obiekt2, które są klasy TablicaD dodać, ten nowo utworzony obiekt (nowy_obiekt) wyświetlić na ekranie (tzn. zawartość tej tablicy), czyli jakby wywołać dla tego nowo utworzonego obiektu z funkcji main funkcję składową klasy wyświetl() ?

Nie mogę np. w funkcji main zrobić czegoś takiego (przykładowo jako rozmiar wysyłam do konstruktora 5):

TablicaD suma(5);
suma = obiekt + obiekt2;
suma.wyswietl();

bo wtedy wyrzuca błąd, że nie ma zdefiniowanego działania typu TablicaD = TablicaD. Operator przypisania też trzeba najpierw przeciążyć? Jeśli tak, to jak ?

0

Dlaczego chcesz tam konieczne zwrocic wskaznik?

#include <cstddef>
 
class Array
{
public:
    Array(): size(0), data(NULL) { ; }
    Array(size_t s): size(s), data(new double[s]) { ; }
    Array& operator=(const Array& a)
    {
        delete[] this->data;
        this->data = new double[a.size];
        for(size_t i = 0; i < a.size; ++i)
            this->data[i] = a.data[i];
        this->size = a.size;
        return *this;
    }
    
    Array operator+(const Array& a)
    {
        Array tmp(this->size + a.size);
        size_t i;
        for(i = 0; i < this->size; ++i)
            tmp.data[i] = this->data[i];
        for(size_t j = 0; j < a.size; ++i, ++j)
            tmp.data[i] = a.data[j];
        
        return tmp;
    }
private:
    size_t size;
    double* data;
};
 
int main()
{
    Array a(5);
    Array b(3);
    Array c;
    c = a + b;
    
    return 0;
}

http://ideone.com/TgNtwR

0

Wielkie dzięki, poradziłem sobie ;).

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