====== Základy C++ ======
===== Třídy =====
* třida je obdoba struktury. V C++ lze dokonce psát třídy s funkcemi :)
* při definici se používá viditelnost
* **private** - přístupné pouze pro třídu.
* **protected** - přístupné pro třídu a potomky třidy.
* **public** - přístupné pro všechny
class user {
private:
int age;
string name;
..
public:
void setAge(int new);
}
* třída má konstruktor a desktruktor
* objekt = dynamická/statická instance třídy
* pokud ve třídě máme nějakou const položku, musíme ji inicializovat v konstruktoru, jinak to nejde
class MyClass {
private:
const int number; // deklarace privatni konstantni promenne
MyClass():number(10) {} // konstruktor s definici promenne
}
* static const se inicializuje takto
class MyClass {
private:
static const int number; // deklarace
}
const int MyClass::number = 10; // definice
==== dědičnost ====
* třída dědí vše od svého předchůdce
* při deklaraci podřazené třídy se specifikuje, jakým způsobem namapovat rodičovskou třídu
* zápis ''class Dog : public Animal'' - co je public u rodiče, je i u potomka
* zápis ''class Dog : protected Animal'' - co je public u rodiče, je u potomka jako protected
* zápis ''class Dog : private Animal'' - co je public u rodiče, je u potomka jako private
* virtual
* definuje tzv pozdní vazbu (až při běhu).
* Někdy není v době překladu jasné, jestli se má zavolat metoda podtřídy nebo nadtřidy.
* Klíčové slovo virtual tento problém řeší až při běhu.
* virtuální destruktor
* je potřeba v Base třídě (ze které se dědí) pokud se používá dynamická alokace objektů
* jinak hrozí, že se bude volat pouze destruktor Base třídy - viz triky
* Příklad problému bez virtual:
class Animal {
public:
void eat() { std::cout << "I'm eating generic food."; }
}
class Cat : public Animal {
public:
void eat() { std::cout << "I'm eating a rat."; }
}
//this can go at the top of the main.cpp file
void func(Animal *xyz) { xyz->eat(); }
Animal *animal = new Animal;
Cat *cat = new Cat;
animal->eat(); // outputs: "I'm eating generic food."
cat->eat(); // outputs: "I'm eating a rat."
func(animal) // outputs: "I'm eating generic food."
func(cat) // outputs: "I'm eating generic food."
* pro opravu stačí předělat metodu eat u base třídy na virtuální
class Animal {
public:
virtual void eat() { std::cout << "I'm eating generic food."; }
}
* využívá se to pro definici něčeho jako rozhraní/interface.
* pokud podtřída má nějakou metodu, kterou nadtřída nemá, nelze tuto metodu z nadtřídy zavolat, přestože v objektu nadtřídy máme uložen objekt podtřídy, který tuto metodu má.
* zkrátka, používá se pro případy, kdy potřebujeme definovat u nadtřídy metodu, která v ni není implementovaná
* pokud se metoda neimplementuje, mluvíme o pure virtual metodě, zapisuje se takhle
class Animal {
public:
virtual void eat() =0;
}
* nebo pro změnu chování nějaké metody základní třídy
* v základní třídě nadefinujeme, jak se má metoda chovat
* v určité podtřídě chování virtuální metody předefinujeme
==== polymorfismus ====
http://www.cplusplus.com/doc/tutorial/polymorphism/
mám obecnou třídu a pak specifické podtřídy. V konstruktoru se inicializuje pro každou specifickou třídu něco jiného. Obecná třída má metodu run. Chci udělat frontu (vector) obecné třídy a při zpracování pak volat metodu run, která zachová podle hodnot nastavených v konstruktoru. Problém: jak to do té fronty dostat?
Když mám objekt obecné třídy, nelze jej přetypovat na různé podtřídy.
http://stackoverflow.com/questions/5313322/c-cast-to-derived-class
class Animal { /* Some virtual members */ }
class Dog: public Animal {};
class Cat: public Animal {};
Dog dog;
Cat cat;
Animal& AnimalRef1 = dog; // Notice no cast required. (Dogs and cats are animals).
Animal& AnimalRef2 = cat;
Animal* AnimalPtr1 = &dog;
Animal* AnimlaPtr2 = &cat;
Cat& catRef1 = dynamic_cast(AnimalRef1); // Throws an exception AnimalRef1 is a dog
Cat* catPtr1 = dynamic_cast(AnimalPtr1); // Returns NULL AnimalPtr1 is a dog
Cat& catRef2 = dynamic_cast(AnimalRed2); // Works
Cat* catPtr2 = dynamic_cast(AnimalPtr2); // Works
// This on the other hand makes no sense
// An animal object is not a cat. Therefore it can not be treated like a Cat.
Animal a;
Cat& catRef1 = dynamic_cast(a); // Throws an exception Its not a CAT
Cat* catPtr1 = dynamic_cast(&a); // Returns NULL Its not a CAT.
Animal animal = cat; // This works. But it slices the cat part out and just
// assigns the animal part of the object.
Cat bigCat = animal; // Makes no sense.
// An animal is not a cat!!!!!
Dog bigDog = bigCat; // A cat is not a dog !!!!
std::vector barnYard;
barnYard.push_back(&dog);
barnYard.push_back(&cat);
barnYard.push_back(&duck);
barnYard.push_back(&chicken);
Dog* dog = dynamic_cast(barnYard[1]); // Note: return NULL as this was the cat.
===== SLT kontejnery =====
* array - statické pole. Alokuje se při kompilaci.
* vector - dynamické pole. Automaticky alokuje paměť.