====== 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ěť.