Zaawansowane metody
programowania
yródła:
J. Grębosz - Symfonia C++
J. Grębosz - Pasja C++
N.M. Josuttis - C++. Biblioteka standardowa. Podręcznik programisty
Podręcznik C++ - http://pl.wikibooks.org/wiki/C++
C++ bez cholesterolu - http://www.intercon.pl/~sektor/cbx/
Klasa
... to inaczej typ.
Definiując klasy tworzymy własne typy danych wykorzystywanych
w programach.
Klasa posiada składniki, którymi mogą być
- dane
- funkcje
... czyli definiuje zbiór określonych danych oraz wykonywanych na
nich operacji
==> ENKAPSULACJA
Klasa
Etykiety określające dostęp do składników klasy
private:
deklarowane za tą etykietą składniki (dane i funkcje) są
dostępne tylko z wnętrza klasy
protected:
składniki są traktowane jako prywatne z tą różnicą, że
widoczne są także przez klasy wywodzące się z danej klasy
public:
składniki są dostępne bez ograniczeń; najczęściej są nimi
funkcje wywoływane z zewnątrz
Klasa
class Car {
private:
std::string brand;
protected:
std::string model;
public:
std::string color;
void setBrand(std::string b);
std::string getBrand();
};
Klasa
int main() {
class Car {
private:
Car c;
std::string brand;
protected:
c.brand = "Audi";
std::string model;
public:
c.model = "A6";
std::string color;
void setBrand(std::string b);
std::string getBrand();
c.color = "black";
};
}
// implementacja
Klasa
int main() {
class Car {
private:
Car c;
std::string brand;
// zle
protected:
c.brand = "Audi";
std::string model;
// zle
public:
c.model = "A6";
std::string color;
void setBrand(std::string b);
// OK
std::string getBrand();
c.color = "black";
};
}
// implementacja
Klasa
Dobre praktyki
class Car {
- dane składowe
private:
niewidoczne,
std::string brand;
std::string color;
- dostęp do nich
protected:
std::string model; za pomocą
publicznych metod
public:
void setBrand(std::string b);
std::string getBrand();
void setColor(std::string c);
std::string getColor();
};
Klasa
Definicja funkcji
class Car {
private:
wewnątrz
std::string brand;
definicji klasy
std::string color;
protected:
std::string model;
public:
void setBrand(std::string b) {
brand = b;
}
std::string getBrand() {
Jeśli już to tylko
return brand;
}
dla krótkich
funkcji (1-2 linie
void setColor(std::string c) {
implementacji)
color = c;
}
std::string getColor() {
return color;
}
};
Klasa
Definicja klasy Definicja funkcji
class Car { void Car::setBrand(std::string b) {
private: brand = b;
std::string brand; }
std::string color;
std::string Car::getBrand() {
protected: return brand;
std::string model; }
public: void Car::setColor(std::string c) {
void setBrand(std::string b); color = c;
std::string getBrand(); }
void setColor(std::string c); std::string Car::getColor() {
std::string getColor(); return color;
}; }
Klasa
Przestrzeń nazw std::
class Car { using namespace std;
private:
std::string brand; class Car {
std::string color; private:
string brand;
protected: string color;
std::string model;
protected:
public: string model;
void setBrand(std::string b);
std::string getBrand(); public:
void setBrand(string b);
void setColor(std::string c); string getBrand();
std::string getColor();
}; void setColor(string c);
string getColor();
};
Klasa
Tworzenie obiektów
int main() {
Car samochod;
samochod.setBrand("Opel");
cout << samochod.getBrand() << endl;
// ?
}
Klasa
Tworzenie obiektów
int main() {
Car samochod;
samochod.setBrand("Opel");
cout << samochod.getBrand() << endl;
// Opel
Car & osobowy = samochod; // referencja
cout << osobowy.getBrand() << endl;
// ?
}
Klasa
Tworzenie obiektów
int main() {
Car samochod;
samochod.setBrand("Opel");
cout << samochod.getBrand() << endl;
// Opel
Car & osobowy = samochod; // referencja
cout << osobowy.getBrand() << endl;
// Opel
osobowy.setBrand("Ford");
cout << samochod.getBrand() << endl;
// ?
}
Klasa
Tworzenie obiektów
int main() {
Car samochod;
samochod.setBrand("Opel");
cout << samochod.getBrand() << endl;
// Opel
Car & osobowy = samochod; // referencja
cout << osobowy.getBrand() << endl;
// Opel
osobowy.setBrand("Ford");
cout << samochod.getBrand() << endl;
// Ford
}
Klasa
Tworzenie obiektów
int main() {
Car samochod;
samochod.setBrand("Opel");
Car * cPtr;
cPtr = &samochod;
cout << cPtr->getBrand() << endl;
// ?
}
Klasa
Tworzenie obiektów
int main() {
Car samochod;
samochod.setBrand("Opel");
Car * cPtr;
cPtr = &samochod;
cout << cPtr->getBrand() << endl;
// Opel
cPtr->setBrand("VW");
cout << samochod.getBrand() << endl;
// ?
}
Klasa
Tworzenie obiektów
int main() {
Car samochod;
samochod.setBrand("Opel");
Car * cPtr;
cPtr = &samochod;
cout << cPtr->getBrand() << endl;
// Opel
cPtr->setBrand("VW");
cout << samochod.getBrand() << endl;
// VW
}
Klasa
Referencje i wskazniki
int main() {
Car samochod;
samochod.setBrand("Opel");
// referencja
// wskaznik
Car & osobowy = samochod;
Car * cPtr;
cout << osobowy.getBrand()
cPtr = &samochod;
<< endl;
cout << cPtr->getBrand()
<< endl;
// ...
}
Klasa
Referencje i wskazniki
int main() {
Car samochod;
samochod.setBrand("Opel");
// referencja
// wskaznik
Car & osobowy = samochod;
Car * cPtr;
cout << osobowy.getBrand()
cPtr = &samochod;
<< endl;
cout << cPtr->getBrand()
<< endl;
// błąd
// ...
Car & osobowy;
}
osobowy = samochod;
Klasa
Dynamiczne tworzenie obiektów
int main() {
Car * cPtr = new Car;
cPtr->setBrand("Citroen");
cout << cPtr->getBrand() << endl;
delete cPtr;
}
Klasa
Dynamiczne tworzenie obiektów
int main() {
Car * cPtr = new Car;
cPtr->setBrand("Citroen");
cout << cPtr->getBrand() << endl;
delete cPtr;
int n = 5;
Car * tab = new Car[n];
// ...
delete [] tab;
}
Klasa
Dynamiczne tworzenie obiektów
int main() {
Car * cPtr = new Car;
cPtr->setBrand("Citroen");
cout << cPtr->getBrand() << endl;
delete cPtr;
int n = 5;
Tu warto sprawdzić, czy
Car * tab = new Car[n];
przypadkiem nie zabrakło pamięci:
// ...
if (tab == NULL) {
delete [] tab;
// hmm... i co tu robić?
}
}
Klasa
Dynamiczne tworzenie obiektów
Jeśli uciekło nam
int main() {
z głowy,
a prowadzący jeszcze tego
Car * cPtr = new Car;
nie podkreślił...
cPtr->setBrand("Citroen");
W języku C++
cout << cPtr->getBrand() << endl;
zmienne (obiekty)
delete cPtr;
można deklarować
w (prawie) dowolnym
int n = 5;
miejscu w programie,
Car * tab = new Car[n];
a nie jedynie
// ...
na początku bloku
delete [] tab;
jak to miało miejsce
}
w C
Klasa
Odejdzmy od samochodów...
Stwórzmy klasę, która będzie
przechowywać takie
informacje jak nazwisko
delikwenta, jego wiek oraz
fakt bycia (lub nie) palaczem...
Klasa
Odejdzmy od samochodów...
class Person {
Stwórzmy klasę, która będzie
string name;
przechowywać takie
int age;
informacje jak nazwisko
bool smoker;
delikwenta, jego wiek oraz
fakt bycia (lub nie) palaczem...
public:
// gettery
string getName();
int getAge();
bool isSmoker();
// settery
// ...
};
Klasa
class Person { int main() {
string name;
int age; Person p;
bool smoker; cout << p.getName() << endl;
// ?
public: cout << p.getAge() << endl;
// gettery // ?
string getName(); cout << p.isSmoker() << endl;
int getAge(); // ?
bool isSmoker(); }
// settery
// ...
};
Klasa
class Person { int main() {
string name;
int age; Person p;
bool smoker; cout << p.getName() << endl;
//
public: cout << p.getAge() << endl;
// gettery // 4072576
string getName(); cout << p.isSmoker() << endl;
int getAge(); // 48
bool isSmoker(); }
// settery
trochę bez sensu...
// ...
};
Klasa
class Person {
string name;
int age;
bool smoker;
public:
Person();
konstruktor
// ...
};
Person::Person() {
age = 18;
smoker = true;
}
Klasa
class Person { int main() {
string name;
int age; Person p;
bool smoker; cout << p.getName() << endl;
//
public: cout << p.getAge() << endl;
Person(); // 18
// ... cout << p.isSmoker() << endl;
}; // 1
}
Person::Person() {
age = 18;
jest lepiej...
smoker = true;
}
Klasa
class Person {
string name;
int age = 18;
bool smoker = true;
Tak nie można!
public:
// ...
};
Inicjalizować składowe dane klasy można tylko w ciele konstruktora lub
na liście inicjalizacyjnej (o tym pózniej)
Klasa
Nadawanie danym składowym wartości w chwili tworzenia obiektów
class Person { Person::Person() {
string name; age = 18;
int age; smoker = true;
bool smoker; }
public: // można wprowadzić własne
Person(); Person::Person(int a, bool s) {
Person(int a, bool s); age = a;
}; smoker = s;
}
Klasa
Można pozbyć się konstruktora:
Person();
i pozostawić tylko ten drugi:
Person::Person(int a, bool s);
nie tracąc poprzedniej funkcjonalności...
...pod warunkiem następującej definicji konstruktora:
Person::Person(int a = 18, bool s = false) {
age = a;
smoker = s;
}
Klasa
int main() {
Przy tak zdefiniowanym konstruktorze:
Person::Person(int a = 18,
Person p1;
bool s = false) {
// wiek: 18, palacz: nie
age = a;
smoker = s;
Person p2(21, true);
}
// wiek: 21, palacz: tak
Person p3(30);
// wiek: 30, palacz: nie
Person p4(true);
// wiek: 1, palacz: nie
}
Klasa
Abstrahując...
class Person { int main() {
string name;
int age; Person p;
bool smoker; p.age = 20;
// czy mogę tak?
// dalsze składniki ...
}; }
Klasa
I jeszcze ważna uwaga...
class Person {
Automatycznie zostanie wygenerowany
string name;
domyślny konstruktor (nie przyjmujący
int age;
parametrów) nie inicjalizujący żadnych
bool smoker;
danych składowych.
public:
Person::Person() {}
// brak konstruktorów
// publiczne metody
};
Klasa
I jeszcze ważna uwaga...
class Person { Person::Person(int a, bool s) {
string name; age = a;
int age; smoker = s;
bool smoker; }
public:
Person::Person(int a, bool s);
};
Jeśli w klasie został zdefiniowany jakiś konstruktor przyjmujący parametry,
domyślny konstruktor (bezargumentowy) nie zostanie automatycznie
wygenerowany. Innymi słowy, w programie nie stworzymy obiektu w ten sposób:
Person p;
Klasa
I jeszcze ważna uwaga...
class Person { Person::Person(int a, bool s) {
string name; age = a;
int age; smoker = s;
bool smoker; }
public: Person::Person() {}
Person();
Person(int a, bool s);
};
Chcąc mieć taką możliwość (i dane składowe zainicjalizować pózniej za pomocą
metod), należy jawnie zadeklarować bezargumentowy konstruktor. Teraz można:
Person p;
Klasa
Skoro był konstruktor to i powinien... destruktor?
Totolotek::Totolotek(int ile) {
class Totolotek {
n = ile;
private:
tablicaLiczb = new int[n];
int n;
srand(time(NULL));
int * tablicaLiczb;
losuj();
public:
}
Totolotek(int ile);
Totolotek::~Totolotek() {
~Totolotek();
delete [] tablicaLiczb;
int * pokazLiczby() {
}
return tablicaLiczb;
void Totolotek::losuj() {
}
for (int i = 0; i < n; i++) {
private:
*(tablicaLiczb + i) = rand();
void losuj();
}
};
}
Klasa
Składniki statyczne
Statyczne dane składowe są wspólne dla wszystkich obiektów danej klasy.
Zmiana wartości danych statycznych dowolnego obiektu określonej klasy jest od
razu widoczna przez wszystkie inne obiekty tej klasy.
Sklep
wszystko po 5zł
Klasa
Składniki statyczne
Towar::Towar(string n) {
class Towar {
nazwa = n;
private:
}
string nazwa;
void Towar::ustawCene(float
static float cena;
nowaCena) {
cena = nowaCena;
public:
}
Towar(string n);
void Towar::podajCene() {
void ustawCene(float
return cena;
nowaCena);
}
float podajCene();
float Towar::cena = 5;
};
Nadać wartość można w momencie inicjalizacji
Sklep
wszystko po 5zł
Klasa
Składniki statyczne
Statyczne dane składowe są wspólne dla wszystkich obiektów danej klasy.
Zmiana wartości danych statycznych dowolnego obiektu określonej klasy jest od
razu widoczna przez wszystkie inne obiekty tej klasy.
int main() {
Towar t1("kubek");
Towar t2("ksiazka");
Towar t3("flakon");
t1.ustawCene(4.50);
cout << t3.podajCene() << endl;
// 4.50
}
Sklep
wszystko po 5zł
Klasa
Składniki statyczne
Statyczne funkcje składowe
int main() {
class Towar {
Towar::ustawCene(5.50);
private:
Towar t1("kubek");
string nazwa;
Towar t3("flakon");
static float cena;
cout << t3.podajCene()
<< endl;
public:
// 5.50
Towar(string n);
t1.ustawCene(4.50);
static void ustawCene(float nowaCena);
cout << t3.podajCene()
float podajCene();
<< endl;
};
// 4.50
}
Klasa
Składniki statyczne - przykład
class Book {
- konieczna deklaracja obiektu (zmiennej)
private:
statycznego (podobnie jak globalnego)
string title;
static int count;
// ...
- statyczna zmienna int jest
public:
Book();
inicjalizowana zerem (podobnie jak
static int getCounter();
// ... zmienna globalna)
};
int Book::count;
Book::Book() {
count++;
}
int Book::getCounter() {
return count;
}
Klasa
Składniki statyczne - przykład
class Book {
- konieczna deklaracja obiektu (zmiennej)
private:
statycznego (podobnie jak globalnego)
string title;
static int count;
// ...
- statyczna zmienna int jest
public:
Book();
inicjalizowana zerem (podobnie jak
static int getCounter();
// ... zmienna globalna)
};
int main() {
int Book::count;
for (int i = 0; i < 100; i++) {
Book::Book() {
Book b;
count++;
}
}
cout << Book::getCounter()
<< endl;
int Book::getCounter() {
// 100
return count;
}
}
Klasa
Dane składowe const
/**
double Kolarz::podajPole(double r) {
* Klasa definiujaca
return pi * r * r;
* operacje na kole
}
*/
class Kolarz {
double Kolarz::podajObwod(double r) {
private:
return 2 * pi * r;
const double pi;
}
public:
Kolarz();
double podajPole(double r);
double podajObwod(double r);
};
Klasa
Dane składowe const
/**
double Kolarz::podajPole(double r) {
* Klasa definiujaca
return pi * r * r;
* operacje na kole
}
*/
class Kolarz {
double Kolarz::podajObwod(double r) {
private:
return 2 * pi * r;
const double pi;
}
public:
Kolarz::Kolarz() {
Kolarz();
pi = 3.1415926;
double podajPole(double r);
}
double podajObwod(double r);
};
Klasa
Dane składowe const
/**
double Kolarz::podajPole(double r) {
* Klasa definiujaca
return pi * r * r;
* operacje na kole
}
*/
class Kolarz {
double Kolarz::podajObwod(double r) {
private:
return 2 * pi * r;
const double pi;
}
public:
Kolarz::Kolarz() {
Kolarz();
pi = 3.1415926;
double podajPole(double r);
}
double podajObwod(double r);
};
Klasa
Dane składowe const
/**
double Kolarz::podajPole(double r) {
* Klasa definiujaca
return pi * r * r;
* operacje na kole
}
*/
class Kolarz {
double Kolarz::podajObwod(double r) {
private:
return 2 * pi * r;
const double pi;
}
public:
Kolarz::Kolarz() : pi(3.1415926) {
Kolarz();
// inicjalizacja obiektów
double podajPole(double r);
// nie-const
double podajObwod(double r);
}
};
Obiekty nie-const mogą być inicjalizowane również na liście inicjalizacyjnej
Klasa
Wróćmy do samochodów
class Car {
Stwórzmy funkcję służącą do
private:
wypisywania na ekranie danych na temat
string brand;
string color;
konkretnego samochodu.
protected:
string model;
Funkcja taka będzie wymagała
przekazania jej obiektu typu Car.
public:
void setBrand(string b);
string getBrand();
Obiekt typu Car może zostać przekazany
void setModel(string m);
do funkcji przez:
string getModel();
- wartość
void setColor(string c);
- referencję
string getColor();
- wskaznik
};
Klasa
Przekazywanie obiektu do funkcji
- przez wartość
void wypisz(Car c) {
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
- przez referencję
void wypisz(Car & c) {
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
- przez wskaznik
void wypisz(Car * c) {
cout << c->getBrand() << endl;
cout << c->getModel() << endl;
cout << c->getColor() << endl;
}
Klasa
Przekazywanie obiektu do funkcji
- przez wartość
void wypisz(Car c) {
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
albo
- przez referencję
void wypisz(Car & c) {
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
- przez wskaznik
void wypisz(Car * c) {
cout << c->getBrand() << endl;
cout << c->getModel() << endl;
cout << c->getColor() << endl;
}
Klasa
Przekazywanie obiektu do funkcji
int main() {
// wywolanie w przypadku przekazywania przez
// wartosc lub referencje
Car c1;
c1.setBrand("Audi");
c1.setModel("A6");
c1.setColor("black");
wypisz(c1);
// wywolanie w przypadku przekazywania przez
// wskaznik
Car * cPtr = &c1;
wypisz(cPtr);
}
Klasa
Zagadka
void wypisz(Car c) {
c.setBrand("noname");
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
int main() {
Car c1;
c1.setBrand("Audi");
c1.setModel("A6");
c1.setColor("black");
wypisz(c1);
cout << c1.getBrand() << endl;
}
Klasa
Zagadka
void wypisz(Car c) {
c.setBrand("noname");
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
int main() { Wynik:
Car c1; noname
c1.setBrand("Audi"); A6
c1.setModel("A6"); black
c1.setColor("black"); Audi
wypisz(c1);
cout << c1.getBrand() << endl;
}
Klasa
Zagadka
void wypisz(Car & c) {
c.setBrand("noname");
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
int main() {
Car c1;
c1.setBrand("Audi");
c1.setModel("A6");
c1.setColor("black");
wypisz(c1);
cout << c1.getBrand() << endl;
}
Klasa
Zagadka
void wypisz(Car & c) {
c.setBrand("noname");
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
int main() { Wynik:
Car c1; noname
c1.setBrand("Audi"); A6
c1.setModel("A6"); black
c1.setColor("black"); noname
wypisz(c1);
cout << c1.getBrand() << endl;
}
Klasa
Jeśli chcemy zapewnić użytkownika, że funkcja nie naruszy mu
obiektu, do którego referencję przesyła:
void wypisz(const Car & c) {
// c.setBrand("noname"); <- tego już kompilator nie puści
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
Klasa
Jeśli chcemy zapewnić użytkownika, że funkcja nie naruszy mu
obiektu, do którego referencję przesyła:
void wypisz(const Car & c) {
// c.setBrand("noname"); <- tego już kompilator nie puści
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
std::string Car::getBrand() const {
class Car {
return brand;
private:
}
string brand;
// ...
public:
string getBrand() const;
// ...
};
Klasa
Jeśli chcemy zapewnić użytkownika, że funkcja nie naruszy mu
obiektu, do którego referencję przesyła:
void wypisz(const Car & c) {
// c.setBrand("noname"); <- tego już kompilator nie puści
cout << c.getBrand() << endl;
cout << c.getModel() << endl;
cout << c.getColor() << endl;
}
std::string Car::getBrand() const {
class Car {
return brand;
private:
}
string brand;
// ...
Podobnie można zrobić
public:
przy przekazywaniu
string getBrand() const;
przez wskaznik
// ...
};
Klasa
Konstruktor kopiujący
void wypisz(Car c) {
Przy przekazywaniu obiektu przez
// ...
wartość zostaje niejawnie wywołany
}
domyślny konstruktor kopiujący, który
powiela wartości poszczególnych
zmiennych: brand, model, color
Klasa
Konstruktor kopiujący
void wypisz(Car c) {
Przy przekazywaniu obiektu przez
// ...
wartość zostaje niejawnie wywołany
}
domyślny konstruktor kopiujący, który
powiela wartości poszczególnych
zmiennych: brand, model, color
Podobnie rzecz wygląda w momencie
Car funkcja() {
zwracania obiektu przez funkcje poprzez
Car c;
return. Obiekt lokalny jest tu kopiowany,
// ...
jego kopia jest widoczna w miejscu
return c;
wywołania funkcji w programie.
}
Klasa
Konstruktor kopiujący
Konstruktor kopiujący możemy wywołać też jawnie:
Car c1;
c1.setBrand("Audi");
c1.setModel("A6");
c1.setColor("black");
Car c2(c1);
Wynik:
wypisz(c2);
Audi
A6
black
Klasa
Konstruktor kopiujący - problem
class Totolotek {
int main() {
private:
Totolotek losowanie(6);
int n;
Totolotek kopia(losowanie);
int * tablicaLiczb;
// ...
public: }
Totolotek(int ile);
// ...
public:
void losuj();
};
Totolotek::Totolotek(int ile) {
n = ile;
tablicaLiczb = new int[n];
srand(time(NULL));
losuj();
}
Klasa
Konstruktor kopiujący - problem
class Totolotek {
int main() {
private:
Totolotek losowanie(6);
int n;
Totolotek kopia(losowanie);
int * tablicaLiczb;
// ...
public: }
Totolotek(int ile);
- wyświetlając wylosowane elementy z
// ...
public:
tablicyLiczb każdego z obiektów
void losuj();
(losowanie i kopia) dostajemy te same
};
liczby -> OK
Totolotek::Totolotek(int ile) {
- po ponownym wywołaniu metody losuj()
n = ile;
na obiekcie losowanie, liczby zawarte w
tablicaLiczb = new int[n];
srand(time(NULL));
obiekcie kopia są TAKIE SAME jak w
losuj();
obiekcie losowanie -> Nie OK!
}
Klasa
Należy zdefiniować konstruktor kopiujący
class Totolotek {
private:
int n;
int * tablicaLiczb;
public:
Totolotek(int ile);
Totolotek(Totolotek & t)
// ...
public:
void losuj();
};
Totolotek::Totolotek(Totolotek & t) {
n = t.n;
tablicaLiczb = new int[n];
for (int i=0; i
tablicaLiczb[i] = t.tablicaLiczb[i];
}
Klasa
Dziedziczenie
class Samochod {
Samochód
public:
- marka
string marka;
- model
string model;
};
class Osobowy : public Samochod {
Osobowy Ciężarowy
public:
- liczbaOsób - ładowność
int liczbaOsob;
};
class Ciezarowy : public Samochod {
Wywrotka
public:
- wysypAadunek()
float ladownosc;
};
class Wywrotka : public Ciezarowy {
public:
void wysypLadunek();
};
Klasa
Składniki klasy Widoczność w klasach pochodnych Widoczność w programie
podstawowej
private niewidoczne niewidoczne
class Samochod { class Osobowy : public Samochod { int main() {
private: public:
int marka; void f() { Samochod s;
void wysMarke(); wysMarke(); // yLE s.wysMarke(); // yLE
} } }
};
protected widoczne niewidoczne
class Samochod { class Osobowy : public Samochod { int main() {
private: public:
int marka; void f() { Samochod s;
protected: wysMarke(); // OK s.wysMarke(); // yLE
void wysMarke(); } }
} };
public widoczne widoczne
class Samochod { class Osobowy : public Samochod { int main() {
private: public:
int marka; void f() { Samochod s;
public: wysMarke(); // OK s.wysMarke(); // OK
int wysMarke(); } }
} };
Klasa
Składniki klasy Widoczność w klasach pochodnych Widoczność w programie
podstawowej
private niewidoczne niewidoczne
class Samochod { class Osobowy : public Samochod { int main() {
private: public:
int marka; void f() { Samochod s;
void wysMarke(); wysMarke(); // yLE s.wysMarke(); // yLE
Oczywiście można też tak
} } }
};
- publiczna metoda klasy
protected widoczne niewidoczne
podstawowej może być
wywoływana na obiekcie
class Samochod { class Osobowy : public Samochod { int main() {
klasy pochodnej
private: public:
int marka; void f() { Samochod s;
( dotyczy to tylko
protected: wysMarke(); // OK s.wysMarke(); // yLE
void wysMarke(); } }
dziedziczenia publicznego )
} };
public widoczne widoczne
class Samochod { class Osobowy : public Samochod { int main() {
private: public:
int marka; void f() { Osobowy o;
public: wysMarke(); // OK o.wysMarke(); // OK
int wysMarke(); } }
} };
Klasa
Dziedziczenie protected :
class Osobowy : protected Samochod {
// ...
};
- wszystkie składniki publiczne i protected klasy Samochod są w klasie
Osobowy ustawione na protected
Klasa
Dziedziczenie protected :
class Osobowy : protected Samochod {
// ...
};
- wszystkie składniki publiczne i protected klasy Samochod są w klasie
Osobowy ustawione na protected
Dziedziczenie private :
class Osobowy : private Samochod {
// ...
};
- wszystkie składniki publiczne i protected klasy Samochod są w klasie
Osobowy ustawione na private
Klasa
Dziedziczenie
Nie dziedziczą się:
- konstruktor
- destruktor
- operator przypisania
W momencie tworzenia obiektu klasy pochodnej, najpierw wywoływany jest
konstruktor klasy podstawowej (domyślny jeśli na liście inicjalizacyjnej nie
wskażemy inaczej), pózniej konstruktor klasy pochodnej.
W momencie likwidowania obiektu klasy pochodnej, najpierw wywoływany jest
destruktor klasy pochodnej, a po nim klasy podstawowej.
Klasa
Person::Person() {
class Person {
age = 18;
string name;
}
int age;
Person::Person(string p_name,
public:
int p_age) {
Person();
name = p_name;
Person(string name,
age = p_age;
int age);
}
// ...
};
Konstruktory klasy
podstawowej
class Worker : public Person {
string occ;
public:
Worker();
Worker(string name, int age, string occ);
};
Worker::Worker() : Person() {}
Worker::Worker(string p_name,
int p_age, string p_occ) : Person(p_name, p_age) {
occ = p_occ;
}
Klasa
Person::Person() {
class Person {
age = 18;
string name;
}
int age;
Person::Person(string p_name,
public:
int p_age) {
Person();
name = p_name;
Person(string name,
age = p_age;
int age);
}
// ...
};
Konstruktor klasy
podstawowej
class Worker : public Person {
string occ;
public:
Worker();
Worker(string name, int age, string occ);
};
Worker::Worker() {}
Worker::Worker(string p_name,
int p_age, string p_occ) : Person(p_name, p_age) {
occ = p_occ;
}
Klasa
class DuzyLotek : public Totolotek {
class Totolotek {
private:
private:
int n;
int zakres;
int * tablicaLiczb;
public:
public:
DuzyLotek();
Totolotek(int ile);
public:
Totolotek(Totolotek & t)
void losuj(); // do przedefiniowania
// ...
public: };
void losuj();
Jeśli w klasie podstawowej nie ma konstruktora domyślnego,
};
trzeba jawnie wskazać, który ma zostać wywołany
DuzyLotek::DuzyLotek() : Totolotek(6) {
zakres = 49;
}
Klasa
Funkcje wirtualne... za chwilę
class Instrument { int main() {
public:
void graj() { Instrument * iPtr = new Instrument;
cout << "nie wiem jak" iPtr->graj();
<< endl; // ?
}
}; Flet * fPtr = new Flet;
fPtr->graj();
class Flet : public Instrument { // ?
public:
void graj() { Instrument * i2Ptr = new Flet;
cout << "pipipi" << endl; i2Ptr->graj();
} // ?
};
}
Klasa
Funkcje wirtualne... za chwilę
class Instrument { int main() {
public:
void graj() { Instrument * iPtr = new Instrument;
cout << "nie wiem jak" iPtr->graj();
<< endl; // nie wiem jak
}
}; Flet * fPtr = new Flet;
fPtr->graj();
class Flet : public Instrument { // pipipi
public:
void graj() { Instrument * i2Ptr = new Flet;
cout << "pipipi" << endl; i2Ptr->graj();
} // nie wiem jak
};
}
hmm....
Klasa
Funkcje wirtualne
class Instrument { int main() {
public:
void virtual graj() { Instrument * iPtr = new Instrument;
cout << "nie wiem jak" iPtr->graj();
<< endl; // nie wiem jak
}
}; Flet * fPtr = new Flet;
fPtr->graj();
class Flet : public Instrument { // pipipi
public:
void graj() { Instrument * i2Ptr = new Flet;
cout << "pipipi" << endl; i2Ptr->graj();
} // pipipi
};
}
juhu !!
Klasa
Funkcje wirtualne
class Instrument { int main() {
public:
void virtual graj() { Instrument * iPtr = new Instrument;
cout << "nie wiem jak" iPtr->graj();
<< endl; // nie wiem jak
}
}; Flet * fPtr = new Flet;
fPtr->graj();
class Flet : public Instrument { // pipipi
public:
void graj() { Instrument * i2Ptr = new Flet;
cout << "pipipi" << endl; i2Ptr->graj();
} // pipipi
};
}
juhu !!
Klasa
Funkcje wirtualne inny przykład
class Instrument { void zaprezentujSie(Instrument& i) {
i.graj();
public:
}
void virtual graj() {
cout << "nie wiem jak"
int main() {
<< endl;
Instrument i;
}
Flet f;
};
zaprezentujSie(i);
class Flet : public Instrument { // nie wiem jak
public:
zaprezentujSie(f);
void graj() { // pipipi
cout << "pipipi" << endl; }
}
};
Klasa
Funkcje wirtualne inny przykład
Czy potrzebny nam obiekt typu Instrument, skoro i tak nie umie grać?
Klasa Instrument może definiować pewne cechy wspólne (np. nazwę instrumentu).
class Instrument {
int main() {
private:
string nazwa;
Instrument * iPtr = new Instrument;
public:
// PROTEST KOMPILATORA
// setter i getter dla nazwy
void virtual graj() = 0;
Flet * fPtr = new Flet;
};
fPtr->graj();
// pipipi
class Flet : public Instrument {
public:
Instrument * i2Ptr = new Flet;
void graj() {
i2Ptr->graj();
cout << "pipipi" << endl;
// pipipi
}
};
}
Klasa
Funkcje wirtualne inny przykład
Czy potrzebny nam obiekt typu Instrument, skoro i tak nie umie grać?
Klasa Instrument może definiować pewne cechy wspólne (np. nazwę instrumentu).
class Instrument {
Klasa abstrakcyjna
private:
(nie można stworzyć
string nazwa;
obiektu tej klasy)
public:
// setter i getter dla nazwy
void virtual graj() = 0;
Funkcja czysto wirtualna
};
class Flet : public Instrument {
public:
void graj() {
cout << "pipipi" << endl;
}
};
Klasa
Funkcje wirtualne inny przykład
Czy potrzebny nam obiekt typu Instrument, skoro i tak nie umie grać?
Klasa Instrument może definiować pewne cechy wspólne (np. nazwę instrumentu).
class Instrument {
Klasa abstrakcyjna
private:
(nie można stworzyć
string nazwa;
obiektu tej klasy)
public:
// setter i getter dla nazwy
void virtual graj() = 0;
Funkcja czysto wirtualna
};
class Flet : public Instrument {
Może istnieć klasa, której wszystkie
metody są czysto wirtualne.
public:
void graj() {
Taka klasa definiuje tzw.
cout << "pipipi" << endl;
interfejs.
}
};
Klasa
Wirtualny destruktor
Jeśli określona klasa definiuje choć jedną metodę wirtualną, jej destruktor także
powinien być wirtualny.
class Instrument {
private:
string nazwa;
public:
// setter i getter dla nazwy
void virtual graj() {
// implementacja
}
virtual ~Instrument() {
Wirtualny destruktor
// implementacja
}
};
Wyszukiwarka
Podobne podstrony:
ZMP Selbsteinstufung
ZMP
więcej podobnych podstron