c++
I co dalej?
Oczekujesz pomocy czy rozwiązania za Ciebie?
- Jeśli pomocy: pokaż kod, staraj się zastosować do Dlaczego nikt nie odpowiada w moim wątku?
- Jeśli wykonania za Ciebie: http://4programmers.net/Forum/Og%C5%82oszenia_drobne (jestem w stanie wykonać zadanie za zaledwie 250zł)
EE
ewelina bella napisał(a):
Czy ten kod jest prawidłowy?
#include <iostream>
#include <cstdlib>
#include <string>using namespace std;
template<typename t="T">
class zesp {
public :
double re, im ;
};template<typename t="T">
zesp<t> &zesp<t>::operator+(const zesp& a , const zesp& b ) {
zesp<t>wynik=z;
z.re = a.re + b.re ;
z.im = a.im + b.im ;
return z;
}template<typename t="T">
zesp<t> &zesp<t>::operator-(const zesp& a , const zesp& b ) {
zesp<t>wynik=z;
z.re = a.re - b.re ;
z.im = a.im - b.im ;
return z;
}
Nie bardzo.
- używaj tagów
<code>
- zwracasz referencję do zmiennej lokalnej - to UB
- nie spełniasz warunków zadania (
operator*
,operator==
, metody zwracające część rzeczywistą i urojoną) -
operator+
ioperator-
powinny być implementowane w oparciu o odpowiedniooperator+=
ioperator-=
- po co te include'y i dyrektywa using?
Podpinam się do tematu: Czy tak jest poprawnie?
template<typename T = int>
class Zesp {
public:
T re, im;
Zesp(T r = 0, T i = 0)
:re(r), im(i)
{}
Zesp<T> operator+(const Zesp& b) const {
Zesp<T> sum;
sum.re = this->re + b.re;
sum.im = this->im + b.im;
return sum;
}
Zesp<T> operator+= (const Zesp& b) {
this->re += b.re;
this->im += b.im;
return *this;
}
void print() const {
std::cout << "[" << re << " + " << im << "i]" << std::endl;
}
};
nie spełniasz warunków zadania (operator*, operator==, metody zwracające część rzeczywistą i urojoną)
Metoda zwraca obiekt, którego składowymi są część rzeczywista i urojona. Wydaje mi się to poprawnym rozwiązaniem.
Poza tym nie znam innego sposobu na zwrócenie dwóch wartości z funkcji.
template <typename t="T">
int liczba_wystapien(T tab[], int n, T v)
{}
Tego to już wcale nie rozumiem. "T"
jest stałą, więc dla domyślnego parametru szablonu T tab[]
jest totalną głupotą.
Czy może się mylę?
Po kolei:
Niezbyt poprawnie, operator+
jako członek klasy wymusza typ lewego argumentu, przez co kod typu
1 + Zesp<double>(0,1)
się nie skompiluje.
Ponadto operator+
powinien być realizowany w oparciu o operator+=
.
Metoda print
narusza SRP.
Metody zwracające wartość rzeczywistą i urojoną to po prostu zwykłe gettery.
"T"
zostało dodane przez skrypt forum aby ratować błędne formatowanie autora, który nie użył tagów <code>
.
kq napisał(a):
Ponadto
operator+
powinien być realizowany w oparciu ooperator+=
Czy ma to jakieś uzasadnienie wydajnościowe, czy chodzi tylko o DRY?
Afaik wyłącznie DRY. http://en.cppreference.com/w/cpp/language/operators#Binary_arithmetic_operators
Czy to dobry kierunek?
#include <iostream>
template<typename T = int>
class Zesp {
public:
T re, im;
Zesp(T r = 0, T i = 0)
:re(r), im(i)
{}
void setReal(T number) {
this->re = number;
}
void setImage(T number) {
this->im = number;
}
T getReal() {
return this->re;
}
T getImage() {
return this->im;
}
Zesp<T> operator+(const Zesp& b) const {
Zesp<T> sum;
sum.re = this->re + b.re;
sum.im = this->im + b.im;
return sum;
}
Zesp<T> operator+(T number) const {
Zesp<T> sum;
sum.re = this->re + number;
sum.im = this->im;
return sum;
}
friend Zesp<T> operator+(T number, const Zesp<T>& b) {
Zesp<T> sum;
sum.re = number + b.re;
sum.im = b.re;
return sum;
}
Zesp<T> operator+= (const Zesp<T>& b) {
this->re += b.re;
this->im += b.im;
return *this;
}
Zesp<T> operator+= (T number) {
this->re += number;
return *this;
}
friend Zesp<T> operator+= (T number, Zesp<T>& b) {
b.re += number;
return b;
}
friend std::ostream& operator<< (std::ostream& os, const Zesp<T>& b) {
os << "[" << b.re << " + " << b.im << "i]";
return os;
}
};
int main()
{
Zesp<int> a;
a.setReal(4);
a.setImage(6);
Zesp<int> b;
b.setReal(3);
b.setImage(8);
Zesp<int> wynik;
wynik = a + b;
a += b;
std::cout << wynik << ", " << a << ", " << b << std::endl;
std::cout << "[" << wynik.getReal() << " + " << wynik.getImage() << "i]" << std::endl;
wynik = a + 5;
std::cout << wynik << std::endl;
wynik = 5 + a;
std::cout << wynik << std::endl;
Zesp<int> c(2, 2);
std::cout << (a + c) << std::endl;
}
Niepotrzebnie dublujesz operator+
friend Zesp<T> operator+(Zesp<T> left, Zesp<T> const& right)
⟵ to powinno wystarczyć.
Bardzo źle dublujesz operator+=
Teraz jeśli napiszesz
Zesp<double> i(0,1);
5 += i;
zmienisz i
, co jest kompletnie bez sensu!
O setterach nie było nic w zadaniu, ale wygląda ok.
Ogółem wygląda na to, że idziesz w dobrym kierunku.
Wywal następujące metody:
void setReal(T number)
setImage(T number)
T getReal()
T getImage()
niczego nie wnoszą, masz im
i re
publicznie dostępne i tak ma zostać.
Niepotrzebnie dublujesz operator+
Zesp<T> operator+(const Zesp& b) const; // obj_left + obj_right
Zesp<T> operator+(T number) const; // obj_left + zmienna
friend Zesp<T> operator+(T number, const Zesp<T>& b); // zmienna + obj_right
Nie rozumiem jak miałoby mi pomóc friend Zesp<T> operator+(Zesp<T> left, Zesp<T> const& right)
?
Myślałem, że już coś umiem. Widzę jednak, że uczyłem się od d... strony (<-- sorki).
Obsługuje wszystkie wymienione przypadki.
Zesp<double> i(0,1);
1 + i; // 1 zostaje skonwertowane do Zesp<double> za pomocą konstruktora jednoargumentowego - co jest możliwe ponieważ konstruktor ma wartości domyślne i nie jest explicit
i + i; // raczej jasne
i + 1; // jak w pierwszym przypadku
1 + 1; // int + int = int
Dla poćwiczenia popracowałem nad metodami, które były:
Zesp<T> operator+(const Zesp& b) const {
Zesp<T> sum = *this;
return sum += b;
}
Zesp<T> operator+(T number) const {
Zesp<T> sum = *this;
return sum += number;
}
// template <typename T>
friend Zesp<T> operator+(T number, const Zesp<T>& b) {
Zesp<T> sum = b;
return sum += number;
}
Zesp<T> operator+= (const Zesp<T>& b) {
this->re += b.re;
this->im += b.im;
return *this;
}
Zesp<T> operator+= (T number) {
this->re += number;
return *this;
}
Popracowałem też nad friend'em.
Nie obsługuje wynik = 5 + a;