Wydział Elektroniki
Kierunek: AiR
Zaawansowane metody
programowania
Wykład 4
Język C++
Homework: Matrix + Terminator
• Idea: w klasie
Complex
zdefiniowano operator rzutowania na typ
double
• Przeładowano funkcję
greater
pozwalającą na porównywanie liczb
różnych typów
• Działa również porównywanie liczb zespolonych, czego w algebrze się nie
definiuje
• Kompilator wymyślił sobie sam własną algebrę: większa liczba zespolona
to ta, która ma większy moduł
• Usunięcie z definicji klasy operatora rzutowania skutkuje błędem
kompilacji
class Complex
{
double Re,Im;
public:
Complex(float x=0, float y=0): Re(x), Im(y){}
void assign(double r,double i) { Re=r; Im=i; }
void print() { cout << Re << "+" << Im << "i "; }
operator double() { return(sqrt(Re*Re+Im*Im)); } // konwersja na double
};
inline int greater(int i,int j) { return(i>j?i:j); }
inline double greater(double x,double y) { return(x>y?x:y); }
inline Complex greater(Complex w,Complex z) { return(w>z?w:z); }
Język C++
Homework: Matrix + Terminator
Compare 10 and 5 : greater is 10
Compare 3.14159 and 2.71828 : greater is
3.14159
Compare 1+3i and 2+2i : greater is 1+3i
void main(void)
{
int i=10, j=5;
cout << "Compare " << i << " and " << j<< " : greater is " << greater(i,j) << "\n";
double x=4*atan(1.), y=exp(1.);
cout << "Compare " << x << " and " << y<< " : greater is " << greater(x,y) << "\n";
Complex u(1,3), v(2,2),z;
z=greater(u,v);
cout << "Compare "; u.print();
cout << " and "; v.print();
cout << " : greater is "; z.print();
_getch();
}
Język C#
Homework: Matrix + Terminator
public class Compare
{
public static Complex greater(Complex a, Complex b)
{
return a > b ? a : b;
}
public static double greater(double a, double b)
{
return a > b ? a : b;
}
}
public class Complex
{
double Re, Im;
public Complex(float x, float y) { Re = x; Im = y; }
public void print(){
Console.Write("{0}+{1}i", Re, Im);}
public static implicit operator double(Complex c){
return (Math.Sqrt(c.Re * c.Re + c.Im * c.Im));}
}
•
Nie ma wartości domyślnych
•
Operatory zdefiniowane
przez użytkownika muszą
być statyczne
•
Na liście argumentów
muszą być wszystkie
operandy
•
W przypadku operatora
rzutowania trzeba określić,
czy ma on być
implicit
czy
explicit
•
Math.Sgrt
•
Kompilator jest inteligentny
ale bez przesady
•
Program przestaje działać
po usunięciu pierwszej
funkcji – chociaż na
upartego można sobie dalej
poradzić: wpierw
przekształcić liczby
zespolone na typ
double
a
potem skorzystać z drugiej
wersji funkcji
greater
.
Język C#
Homework: Matrix + Terminator
x1 = 4+3i
x2 = 2+5i
Większa liczba to:
y = 2+5i
static void Main()
{
Console.Write("x1 = ");
Complex x1 = new Complex(4, 3);
x1.print();
Console.Write("\nx2 = ");
Complex x2 = new Complex(2, 5);
x2.print();
Console.Write("\nWiększa liczba to:\n y
= ");
Complex y = new Complex(0,0);
y = Compare.greater(x1, x2);
y.print();
Console.ReadKey();
}
Język C#
Zabawa z formatem
class Program
{
static void Main()
{
double x1 = 12.456, x2 = 1.737383, x3, x4;
Console.WriteLine("x1 = {0:F2}", x1);
Console.WriteLine("x2 = {0:F8}", x2);
x3 = Compare.greater(x1, x2);
Console.WriteLine("Większa liczba to:\nx3 =
{0:F5}",x3);
x4 = (int)x3;
Console.WriteLine("x4 = {0:F1}", x4);
Console.WriteLine("x4 = {0}", x4);
Console.ReadKey();
}
}
x1 = 12,46
x2 = 1,73738300
Większa liczba to:
x3 = 12,45600
x4 = 12,0
x4 = 12
Język C#
Operator overloading – VS Help 1
• C# allows
user-defined
types to
overload
operators by
defining static
member
functions
using the
operator
keyword.
• Not all
operators can
be overloaded,
however, and
others have
restrictions.
Operators Overloadability
+ - ! ~
++ --
true false
These unary operators can be overloaded.
+ - * /
% & ^
<< >>
These binary operators can be overloaded.
== != <
> <= >=
The comparison operators can be overloaded.
&& ||
The conditional logical operators cannot be
overloaded, but they are evaluated using & and |
which can be overloaded.
[]
The array indexing operator cannot be overloaded,
but you can define indexers.
()
The cast operator cannot be overloaded, but you can
define new conversion operators (explicit - implicit).
Język C#
Operator overloading – VS Help 2
• Assignment operators
( += -= *= /= %= &= |= ^= <<=
>>= )
cannot be overloaded, but
+=
, for example, is evaluated
using
+
, which can be overloaded.
• Operators
= . ?: -> new is sizeof typeof
cannot be overloaded.
• The comparison operators, if overloaded, must be overloaded
in pairs; that is, if
==
is overloaded,
!=
must also be
overloaded.
• To overload an operator on a custom class requires creating a
method on the class with the correct signature. The method
must be named "
operator X
" where
X
is the name or symbol of
the operator being overloaded.
• Unary operators have one parameter, and binary operators
have two parameters. In each case, one parameter must be the
same type as the class or struct that declares the operator.
Język C#
Przeciążanie operatorów – zasady ogólne
• Operatory przeładowywalne są podzielone w C# na trzy
kategorie:
– jednoargumentowe
– dwuargumentowe oraz
– operatory konwersji.
• Deklaracja operatora musi zawierać zarówno modyfikator
public
jak i modyfikator
static
.
• Parametry operatora muszą być parametrami wartościowymi.
Podanie w deklaracji parametrów
ref
lub
out
powoduje błąd
kompilacji.
• Sygnatura operatora musi różnić się od sygnatur wszystkich
innych operatorów zadeklarowanych w tej samej klasie.
• Każda kategoria operatorów narzuca dodatkowe ograniczenia.
• Operatory są dziedziczone – podobnie jak wszystkie inne
składowe w klasie bazowej.
• Deklaracje operatorów wymagają aby klasa (lub struktura), w
której operator jest deklarowany była uwzględniana w
sygnaturze tego operatora
Język C#
Przeciążanie operatorów – szczegóły
• Operator jednoargumentowy
++
oraz
--
musi przyjmować jeden
argument typu klasa T (lub T?), która zawiera deklarację tego
operatora i musi zwracać taki sam typ.
• Dwuargumentowy operator nie będący operatorem przesunięcia
musi przyjmować dwa parametry, z których przynajmniej jeden
musi być typu T lub T? i może zwracać dowolny typ.
• Dwuargumentowy operator przesunięcia
>>
lub
<<
musi
przyjmować dwa parametry, z których pierwszy musi być typu T
lub T? a drugi musi mieć typ
int
lub
int?
i może zwracać
dowolny typ.
• Niektóre operatory dwuargumentowe muszą być deklarowane
parami to znaczy, że musi być podana deklaracja drugiego z
operatorów pasujących do tej pary. Są to operatory:
– ==
oraz
!=
– >
oraz
<
– >=
oraz
<=
.
• Dwie deklaracje pasują do siebie, gdy mają ten sam typ zwracany
oraz ten sam typ dla każdego z parametrów.
Język C#
Przeciążanie operatorów
jednoargumentowych
public class Complex
{
double Re, Im;
public Complex(float x, float y) { Re = x; Im = y; }
public void print(){
Console.Write("{0}+{1}i", Re, Im);}
public static implicit operator double(Complex c){
return (Math.Sqrt(c.Re * c.Re + c.Im * c.Im));}
}
• Przykład 1 – operator rzutowania
•
W przypadku operatora rzutowania (konwersji) trzeba
określić, czy ma on być
implicit
czy
explicit
Język C#
Przeciążanie operatorów
jednoargumentowych
public void print()
{
Console.Write("{0}+{1}i", Re, Im);
}
public static int operator !(Complex c)
{
c.print();
return 0;
}
• Przykład 2 – operator logicznej negacji
• Operator zdefiniowany w klasie
Complex
• Przy jego definicji wykorzystano funkcję składową, aby nie
powielać kodu
• Przykład użycia:
int s = !x1;
Język C#
Przeciążanie operatorów
dwuargumentowych
public static Complex operator +(Complex a,
Complex b)
{
Complex t = new Complex(0, 0);
t.Re = a.Re + b.Re;
t.Im = a.Im + b.Im;
return t;
}
• Przykład 3 – operator dodawania (liczb zespolonych)
• Operator zdefiniowany w klasie
Complex
• Zwracany jest obiekt tymczasowy
• Operator zachowuje łączność
• Przykład użycia:
y = x1 + x2 + x3;