Przeciążenia operatorów dla klas

Przeciążenia operatorów dla klas
D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
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:

Kopiuj
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:

Kopiuj
#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;
	}

}
/////////////////////////////////////////////////////////////////////////////////////////////
edytowany 2x, ostatnio: Dragon2011
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
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/


D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
0

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

edytowany 1x, ostatnio: Dragon2011
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
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?


Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około godziny
0

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

Kopiuj
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
}
edytowany 2x, ostatnio: Azarien
D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
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.

D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
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:

Kopiuj
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.

edytowany 2x, ostatnio: Dragon2011
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
0

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


D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
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ć ?

edytowany 3x, ostatnio: Dragon2011
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
0

Coś w tym guście:

Kopiuj
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


D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
0

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

Kopiuj
No instance of constructor "TablicaD::TablicaD" matches the argument list.
No suitable constructor exists to convert from "TablicaD *" to "TablicaD" 
edytowany 1x, ostatnio: Dragon2011
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
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.


D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
0

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

Kopiuj
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):

Kopiuj
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 ?

n0name_l
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 4 lata
  • Postów:2412
0

Dlaczego chcesz tam konieczne zwrocic wskaznik?

Kopiuj
#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

D2
  • Rejestracja:ponad 13 lat
  • Ostatnio:ponad 9 lat
  • Postów:72
0

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

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)