Składnia C++ Programowanie Obiektowe Mateusz Cicheński
Klasy i modyfikatory dostępu Przesłanianie metod Polimorfizm Wskaźniki Metody wirtualne Metody abstrakcyjne i interfejsy Przeciążanie operatorów Słowo kluczowe this Konstruktory i destruktory Poza paradygmatem PO Pola statyczne Przyjaciele Dodatkowe informacje Plan zajęć
class Figure { figure.h //pola i metody dostępne tylko dla klasy private: //pola i metody dostępne dla klasy i klas dziedziczących protected: //pola i metody ogólnodostępne public: ; Modyfikatory dostępu
//elementy dziedziczone po klasie nadrzędnej //dostępne tylko dla tej klasy (private) class Rectangle : private Figure { ; rectangle.h //elementy dziedziczone po klasie nadrzędnej rectangle.h //dostępne dla tej klasy i klas dziedziczących (protected) class Rectangle : protected Figure { ; //elementy dziedziczone po klasie nadrzędnej //nie zmieniają typu swojej dostępności class Rectangle : public Figure { ; rectangle.h Modyfikatory dostępu dziedziczenia
class Figure { public: int area(); ; #include figure.h figure.h figure.cpp int Figure::area() { return -1; #include figure.h rectangle.h class Rectangle : public Figure { ; Elementy składowe klasy
#include <iostream> #include figure.h #include rectangle.h main.cpp using namespace std; int main (int argc, char** argv) { Figure figure; Rectangle rectangle; cout << figure.area() << endl; cout << rectangle.area() << endl; return 0; $./main -1-1 output Wykorzystanie klas
#include figure.h class Rectangle : public Figure { protected: int width, height; public: int area(); ; rectangle.h #include rectangle.h rectangle.cpp int Rectangle::area() { return width * height; $./main -1 0 output Przesłanianie metod
#include <iostream> #include figure.h #include rectangle.h main.cpp using namespace std; int main (int argc, char** argv) { Figure figure; Rectangle rectangle; Figure *pointer = NULL; pointer = &figure; cout << pointer->area() << endl; pointer = &rectangle; cout << pointer->area() << endl; return 0; $./main -1-1 output Wskaźniki
Wyrażenie Interpretacja *x Obiekt wskazywany przez x &x x.y x->y (*x).y x[0] x[1] x[n] *(x+n) Adres w pamięci dla x Pole y obiektu x Pole y obiektu wskazywanego przez x jw. Pierwszy obiekt wskazywany przez x Drugi obiekt wskazywany przez x (n+1) obiekt wskazywany przez x jw. Wskaźniki c.d.
class Figure { public: virtual int area(); ; figure.h $./main -1 0 output Metody wirtualne
class Figure { protected: int type; public: virtual int area() = 0; ; #include figure.h figure.h figure.cpp Metody abstrakcyjne (klasy abstrakcyjne)
class IFigure { public: virtual int area() = 0; ; figure.h Interfejsy
#include figure.h rectangle.h class Rectangle : public Figure { protected: int width, height; public: int area(); Rectangle operator + (Rectangle rectangle); ; #include rectangle.h rectangle.cpp int Rectangle::area() { return width * height; Rectangle Rectangle::operator+ (Rectangle rectangle) { Rectangle temp; temp.width = width + rectangle.width; temp.height = height + rectangle.height; return temp; Przeciążenie operatorów
Składnia: typ operator symbol (parametr) { Symbole operatorów do przeciążenia + - * / = < > += -= *= /= << >> <<= >>= ==!= <= >= ++ -- % & ^! ~ &= ^= = && %= [] (), ->* -> new delete new[] delete[] Tabela operatorów do przeciążenia
Wyrażenie Operator Jako metoda klasy @a + - * &! ~ ++ - - A::operator@() Jako funkcja globalna operator@(a) a@ ++ -- A::operator@(int) operator@(a,int) a@b + - * / % ^ & < > ==!= <= >= << >> &&, a@b = += -= *= /= %= ^= &= = <<= >>= [] A::operator@(B) A::operator@(B) operator@(a,b) Przeciążenie wybranych symboli
#include figure.h rectangle.h class Rectangle : public Figure { protected: int width, height; public: Rectangle& operator = (const Rectangle &rectangle); ; #include rectangle.h #include <iostream> rectangle.cpp Rectangle& Rectangle::operator= (const Rectangle &rectangle) { width = rectangle.width; height = rectangle.height; std::cout << Rectangle copy assignment << std:endl; return *this; Słowo kluczowe this
#include <iostream> #include rectangle.h main.cpp using namespace std; int main (int argc, char** argv) { Rectangle rectangle(2,3); Rectangle copy = rectangle; return 0; $./main output Słowo kluczowe this c.d.
#include <iostream> #include rectangle.h main.cpp using namespace std; int main (int argc, char** argv) { Rectangle rectangle(2,3); //Rectangle copy = rectangle; NIE! Rectangle copy; copy = rectangle; return 0; $./main Rectangle copy assignment output Słowo kluczowe this c.d.
class Figure { public: Figure(); virtual int area(); ; #include figure.h figure.h figure.cpp Figure::Figure() { int Figure::area() { return -1; Konstruktor bezargumentowy (domyślny)
#include figure.h rectangle.h class Rectangle : public Figure { protected: int width, height; public: Rectangle(int width, int height); int area(); ; #include rectangle.h rectangle.cpp Rectangle::Rectangle(int width, int height) { this->width = width; this->height = height; int Rectangle::area() { return width * height; Konstruktor z argumentami
#include rectangle.h rectangle.cpp Rectangle::Rectangle(int width, int height) : Figure() { this->width = width; this->height = height; int Rectangle::area() { return width * height; Wywołanie konstruktora klasy nadrzędnej
#include rectangle.h square.h class Square : public Rectangle { public: Square(int width); ; #include square.h #include <iostream> square.cpp Square::Square(int width) : Rectangle(width, width) { Wywołanie konstruktora klasy nadrzędnej c.d.
#include <iostream> #include figure.h #include rectangle.h #include square.h main.cpp using namespace std; int main (int argc, char** argv) { Figure figure; Rectangle rectangle(2,3); Square *square = new Square(2); cout << figure.area() << endl; cout << rectangle.area() << endl; cout << square->area() << endl; return 0; $./main -1 6 4 output Użycie konstruktorów
#include figure.h rectangle.h class Rectangle : public Figure { protected: int width, height; public: Rectangle(int width, int height); Rectangle(const Rectangle &rectangle); ; #include rectangle.h #include <iostream> rectangle.cpp Rectangle::Rectangle(int width, int height) { this->width = width; this->height = height; Rectangle::Rectangle(const Rectangle &rectangle) { width = rectangle.width; height = rectangle.height; std::cout << Rectangle copy constructor << std::endl; Konstruktor kopiujący
#include <iostream> #include rectangle.h main.cpp using namespace std; int main (int argc, char** argv) { Rectangle rectangle(2,3); Rectangle copy(rectangle); return 0; $./main Rectangle copy constructor output Konstruktor kopiujący c.d.
class Figure { public: Figure(); ~Figure(); virtual int area(); ; #include figure.h #include <iostream> figure.h figure.cpp Figure::Figure() { Figure::~Figure() { std::cout << Figure destroyed << std::endl; int Figure::area() { return -1; Destruktor
#include rectangle.h square.h class Square : public Rectangle { public: Square(int width); ~Square(); ; #include square.h #include <iostream> square.cpp Square::Square(int width) : Rectangle(width, width) { Square::~Square() { std::cout << Square destroyed << std::endl; Destruktor c.d.
#include <iostream> #include figure.h #include rectangle.h #include square.h main.cpp using namespace std; int main (int argc, char** argv) { Figure *figure = new Square(2); delete figure; return 0; $./main Figure destroyed output Destruktor wyciek pamięci
class Figure { public: Figure(); virtual ~Figure(); virtual int area(); ; #include figure.h #include <iostream> figure.h figure.cpp Figure::Figure() { Figure::~Figure() { std::cout << Figure destroyed << std::endl; int Figure::area() { return -1; Wirtualny destruktor
#include <iostream> #include figure.h #include rectangle.h #include square.h main.cpp using namespace std; int main (int argc, char** argv) { Figure *figure = new Square(2); delete figure; return 0; $./main Square destroyed Figure destroyed Wirtualny destruktor c.d. output
class Figure { public: Figure(); virtual ~Figure(); static int count; virtual int area(); ; #include figure.h figure.h figure.cpp int Figure::count = 0; Figure::Figure() { count++; Figure::~Figure() { count--; int Figure::area() { return -1; Pola statyczne
#include <iostream> #include figure.h #include rectangle.h main.cpp using namespace std; int main (int argc, char** argv) { Figure figure; Rectangle *rectangle; cout << Figure::count << endl; delete rectangle; cout << Figure::count << endl; return 0; $./main 2 1 output Pola statyczne c.d.
#include rectangle.h square.h class OtherSquare; class Square : public Rectangle { public: Square(int width); ~Square(); friend class OtherSquare; ; Przyjaciele klasy
class Square; othersquare.h class OtherSquare { private: int side; public: void convert(square &square); ; #include othersquare.h #include square.h othersquare.cpp void OtherSquare::convert(Square &square) { side = square.width; Przyjaciele klasy c.d.
class Square; othersquare.h class OtherSquare { private: int side; public: void convert(square &square); friend int getside(othersquare square); ; Przyjaciele funkcje
#include <iostream> #include square.h #include othersquare.h main.cpp using namespace std; int getside(othersquare square) { return square.side; int main (int argc, char** argv) { OtherSquare osquare; Square square(2); osquare.convert(square); cout << getside(osquare) << endl; return 0; $./main 2 Przyjaciele funkcje c.d. output
Domyślny modyfikator dostępu: private Domyślnie dla danej klasy kompilator generuje: konstruktor bezargumentowy, konstruktor kopiujący destruktor operator przypisania (=) z parametrem w postaci implementowanej klasy Ale: definicja dowolnego konstruktora powoduje, że kompilator nie generuje konstruktora bezargumentowego Dodatkowe informacje
W ramach statycznej metody klasy nie można odwoływać się do pól właściwych dla instancji klasy (jedynie do pól statycznych) Pola/metody statyczne w klasie posiadają modyfikatory dostępu Przyjaciel mojego przyjaciela nie jest moim przyjacielem relacja nie jest przechodnia Przyjaciel nie jest relacją symetryczną Dodatkowe informacje c.d.
Pytania? http://bit.ly/oop2014