Funkcje wirtualne, klasy abstrakcyjne

    • prawdziwy polimorfizm - dysponując wskaźnikiem lub referencją klasy bazowej możemy uruchomić metodę wirtualną klasy pochodnej
    • metoda abstrakcyjna to metoda wirtualna, która posiada tylko deklarację w klasie bazowej, musi być zaimplementowana w klasie pochodnej)
    • klasa abstrakcyjna to klasa, która posiada przynajmniej jedną metodę abstrakcyjną, nie można stworzyć obiektu tego typu, jedynie obiekty klas pochodnych
  • kwalifikator override od C++11
  • dynamiczne rzutowanie dynamic_cast<Typ>

Przykład funkcji wirtualnej

class Bazowa
{
public:
   virtual void Wirtualna()
   {
      /* implementacja w klasie bazowej */
   }
};
 
class Pochodna : public Bazowa
{
public:
   virtual void Wirtualna() override
   {
      /* implementacja w klasie pochodnej */ 
   }
};

Przykład funkcji abstrakcyjnej

class KlasaAbstrakcyjna
{
    virtual int Wirtualna() = 0;
};

Przykład rzutowania dynamicznego

Bazowa *bazowa = new Bazowa();
Pochodna *pochodna = dynamic_cast<Pochodna*>(bazowa);
 
if(pochodna) { /* tylko gdy pochodna dziedziczy po bazowej */ }

Program rozszerza implementację programu z poprzednich zajęć, którego źródła znajdziesz w zakładce pliki lub w repozytorium GitHub.

1. Utwórz klasę Gauss - reprezentującą funkcję Gaussa zawierającą:

  • dwa pola o wartościach rzeczywistych: srednia i odchylenie
  • konstruktor pozwalający zainicjować funkcję Gaussa wartością średnią i odchyleniem
  • konstruktor domniemany inicjujący funkcję Gaussa ze średnią 0 i odchyleniem 1
  • metodę ObliczWartosc wyznaczającą wartość funkcji w punkcie $x$. Funkcja Gaussa o wartości średniej $\mu$ i odchyleniu $\sigma$ dana jest wzorem

$$f(x)=\frac{1}{\sigma \sqrt{2 \pi}} \exp \left(\frac{-(x-\mu)^2}{2 \sigma^2}\right)$$

  • zaprzyjaźnioną funkcję przeciążającą operator « wypisujący komunikat do strumienia postaci
    Gauss (srednia=0, odchylenie=1)

2. Utwórz klasę Funkcja, która uogólnia pojecie funkcji i będzie stanowiła klasę bazową klasy Wielomian i klasy Gauss. Jakie cechy (metody, atrybuty) można uogólnić do klasy Funkcja?
Klasa Funkcja zawiera:

  • metodę czysto wirtualną ObliczWartosc
  • zaprzyjaźnioną funkcję przeciążająca operator «

Diagram klas

3. Napisz funkcję globalną o nazwie calka, która zwraca przybliżoną wartość całki funkcji oznaczonej na przedziale $[a,b]$. Obliczenia wykonywane są metodą złożonych prostokątów, gdzie sumujemy pola $n$ prostokątów $h\cdot f(x)$w równoodległych punktach na odcinku $[a, b]$

$$ \int_a^b f(x) \approx h \sum_{i=0}^{n-1} f(a+i \cdot h) \qquad \text{gdzie} \qquad h=\frac{b-a}{n} $$

Argumentami funkcji calka są:

  • dowolna funkcja, która dziedziczy po klasie Funkcja
  • granice przedziału $a$ i $b$
  • liczba węzłów $n$

4. Napisz program, który wyznaczy całkę funkcji Gaussa na przedziale $[\mu, 3\sigma]$ (wartości $\mu$ i $\sigma$ wybierz dowolnie) oraz całkę funkcji kwadratowej $f(x)=x^2$ na odcinku $[0, 1]$. Liczbę węzłów $n$ użytą do wyznaczenia całki podaje użytkownik na początku działania programu.

Przykład działania programu:

Ile wezlow calkowania? 100

Funkcja: Gauss (srednia=3, odchylenie=5)
Przedzial calkowania: [3, 15]
Wynik calkowania = 0.496318

Funkcja: f(x) = 1x^2 
Przedzial calkowania: [0, 1]
Wynik calkowania = 0.32835

Zaimplementuj klasy Figura, Kolo, Kwadrat i Trojkat oraz odpowiednie metody zgodnie z podanym diagramem:

Diagram klas

  • klasa Kolo reprezentuje koło okreslone długością promienia. Konstruktory pozwalają zainicjowac promień koła i nazwę figury. Domniemane wartości to promień 1 i nazwa „Kolo”
  • klasa Kwadrat reprezentuje kwadrat okreslony długością boku. Konstruktory pozwalają zainicjowac długość boku kwadratu i nazwę figury. Domniemane wartości to bok o długości 1 i nazwie „Kwadrat”
  • klasa Trojkat reprezentuje trójkąt równoboczny określony długością boku. Konstruktory pozwalają zainicjowac długość boku trójkąta i nazwę figury. Domniemane wartości to bok o długości 1 i nazwie „Trojkat”
  • klasa Figura reprezentuje abstrakcję dowolnej figury. Konstruktory inicjują nazwę, domniemana wartość nazwy to „Figura”

Każda figura dziedzicząca po klasie Figura implementuje funkcje obliczające pole i obwód danej figury. $$ \begin{array}{lll} P_{\circ}=\pi r^2 \qquad & P_{\square}=a^2 \qquad & P_{\triangle}=\frac{a^2\sqrt{3}}{4} \\ O_{\circ}=2\pi r & O_{\square}=4a & O_{\triangle}=3a \\ \end{array} $$

Dociąż operator przesunięcia bitowego « dla figur w taki sposób aby umieszczał w strumieniu wyjściowym std::ostream napis zawierający nazwę figury, wartość pola oraz obwodu figury, np.:

Kwadrat k(3);
cout << k << endl;
 
Trojkat t(3);
cout << t << endl;

spowoduje wypisanie na konsoli komunikatu postaci

Kwadrat o polu 9 i obwodzie 12
Trojkat o polu 3.89711 i obwodzie 9

Napisz klasę Sumator, której zadaniem jest sumowanie pól powierzchni figur. Klasa posiada pole suma o wartości rzeczywistej oraz udostępnia następujące operacje:

  • konstruktor domyślny inicjuje sumator suma=0
  • funkcję składową Dodaj, która przyjmuje w argumencie dowolną figurę (obiekt pochodny klasy Figura) i dodaje do pola suma wartość pola podanej figury
  • funkcja składowa Wynik() zwraca aktualną wartość sumy pół figur, które dotychczas zostały dodane metodą Dodaj.

Napisz program wykorzystujący klasę Sumator do policzenia sumy pól n kół o promieniach $r=1, 2, 3, \ldots, n$ i $n$ kwadratów o bokach $a=1, 2, 3, \ldots, n$ oraz $n$ trójkątów równoramiennych o bokach $a=1, 2, 3, \ldots, n$. Wartość całkowitą $n$ podaje użytkownik na początku działania programu.

Przykład działania programu:

n=3

1: dodaje Kolo o polu 3.1415 i obwodzie 6.283
2: dodaje Kolo o polu 12.566 i obwodzie 12.566
3: dodaje Kolo o polu 28.2735 i obwodzie 18.849

1: dodaje Kwadrat o polu 1 i obwodzie 4
2: dodaje Kwadrat o polu 4 i obwodzie 8
3: dodaje Kwadrat o polu 9 i obwodzie 12

1: dodaje Trojkat o polu 0.433013 i obwodzie 3
2: dodaje Trojkat o polu 1.73205 i obwodzie 6
3: dodaje Trojkat o polu 3.89711 i obwodzie 9

Suma pol wynosi 64.0432

Rozwiązanie w postaci plików nagłówkowych *.h i źródłowych *.cpp umieść w Moodle Zadanie 7