lang:cpp:classes
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
lang:cpp:classes [2020/05/13 11:31] – Fin de la définition de la règle des 5 / 0 root | lang:cpp:classes [2022/07/04 10:05] (Version actuelle) – [Destructeur] : lock_guard->scoped_lock root | ||
---|---|---|---|
Ligne 3: | Ligne 3: | ||
====Multiples constructeurs==== | ====Multiples constructeurs==== | ||
Il est possible d' | Il est possible d' | ||
+ | |||
+ | Bien qu'on soit dans le paragraphe sans héritage, j'ai mis un cas avec héritage pour montrer qu'on a pas besoin d' | ||
<code cpp> | <code cpp> | ||
Ligne 10: | Ligne 12: | ||
| | ||
// Call constructor B(int) from constructor B(). | // Call constructor B(int) from constructor B(). | ||
- | // Dont call the parent A() when calling another constructor of the same class. | + | // No need (forbidden) to call A. |
B() : B(5){} | B() : B(5){} | ||
// Avoid default function argument | // Avoid default function argument | ||
Ligne 145: | Ligne 147: | ||
< | < | ||
const | const | ||
+ | </ | ||
+ | |||
+ | * Durée de vie d'un objet dans la pile | ||
+ | |||
+ | Si c'est un objet explicitement déclaré, le destructeur sera appelé lors du bloc fermant. | ||
+ | |||
+ | <code cpp> | ||
+ | int main() | ||
+ | { | ||
+ | A a; | ||
+ | { | ||
+ | B b; | ||
+ | // On appelle ~B() | ||
+ | } | ||
+ | // On appelle ~A() | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | La technique de mettre un bloc de crochet pour forcer un appel du destructeur à un moment précis est utilisé fréquemment par les '' | ||
+ | |||
+ | <code cpp> | ||
+ | int main() | ||
+ | { | ||
+ | std::mutex io_mutex; | ||
+ | { | ||
+ | std:: | ||
+ | std::cout << e1.id << " and " << e2.id << " are waiting for locks" << std::endl; | ||
+ | // le mutex est automatiquement libéré lors de l' | ||
+ | } | ||
+ | return 1; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Si l' | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | |||
+ | class A | ||
+ | { | ||
+ | public: | ||
+ | A() noexcept { std::cout << " | ||
+ | ~A() noexcept { std::cout << " | ||
+ | int foo() { return 1; } | ||
+ | }; | ||
+ | |||
+ | int foo2(int a) | ||
+ | { | ||
+ | std::cout << " | ||
+ | return a; | ||
+ | } | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | std::cout << " | ||
+ | foo2(foo2(A().foo())); | ||
+ | // Le destructeur de A est appelé ici. | ||
+ | std::cout << " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Affichage : | ||
+ | |||
+ | < | ||
+ | 0 | ||
+ | A | ||
+ | int | ||
+ | int | ||
+ | ~A | ||
+ | 1 | ||
</ | </ | ||
Ligne 222: | Ligne 294: | ||
L' | L' | ||
+ | |||
+ | Mauvais : | ||
<code cpp> | <code cpp> | ||
Ligne 240: | Ligne 314: | ||
D d; | D d; | ||
f(d); | f(d); | ||
+ | </ | ||
+ | |||
+ | OK : | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | |||
+ | class B { | ||
+ | | ||
+ | B() = default; | ||
+ | // Si on implémente ce clone, il faut mettre le constructeur par copie en public. | ||
+ | // Il est préférable de mettre ce constructeur en privée pour empêcher | ||
+ | // sa mauvaise utilisation. | ||
+ | virtual std:: | ||
+ | virtual char m() { return 1; } | ||
+ | virtual ~B() = default; | ||
+ | |||
+ | | ||
+ | // Peut être protected si clone est pure virtuelle. | ||
+ | B(const B&) = default; | ||
+ | B& operator=(const B&) = delete; | ||
+ | }; | ||
+ | |||
+ | class D : public B { | ||
+ | | ||
+ | D() = default; | ||
+ | D(const D&) = default; | ||
+ | D& operator=(const D&) = delete; | ||
+ | std:: | ||
+ | char m() override { return 10; } | ||
+ | virtual ~D() = default; | ||
+ | }; | ||
+ | |||
+ | char f(B& b) { | ||
+ | auto b2 = b.clone(); | ||
+ | return b2->m(); | ||
+ | } | ||
+ | |||
+ | int main() { | ||
+ | D d; | ||
+ | return f(d); | ||
+ | } | ||
</ | </ | ||
Ligne 404: | Ligne 520: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | ====vtable==== | ||
+ | |||
+ | Il n' | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | |||
+ | struct S { | ||
+ | int x; | ||
+ | virtual void f() {} | ||
+ | }; | ||
+ | |||
+ | int main() { | ||
+ | S s; | ||
+ | s.x = 5; | ||
+ | std::cout << "size : " << sizeof(S) << " | ||
+ | void*** ptr = (void***)& | ||
+ | std::cout << " | ||
+ | std::cout << "bytes : " << *ptr << " and " << *(ptr + 1) << " | ||
+ | std::cout << " | ||
+ | << " | ||
+ | std:: | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[http:// | ||
+ | |||
====override / redéfinition==== | ====override / redéfinition==== | ||
===Cas général=== | ===Cas général=== | ||
Ligne 446: | Ligne 591: | ||
Pour le destructeur, | Pour le destructeur, | ||
+ | Par défaut, un destructeur est '' | ||
====overload / surcharge==== | ====overload / surcharge==== | ||
* Cas général | * Cas général | ||
Ligne 529: | Ligne 675: | ||
</ | </ | ||
+ | ====Interface==== | ||
+ | |||
+ | Il n'y a pas une unique méthode pour définir une interface. | ||
+ | |||
+ | ===Classe abstraite=== | ||
+ | |||
+ | Il faut faire une classe avec tous les prototypes et les déclarer toutes virtuelles pures. | ||
+ | |||
+ | '' | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | struct BaseClass | ||
+ | { | ||
+ | virtual ~BaseClass() = default; | ||
+ | virtual std::string getName() const = 0; | ||
+ | }; | ||
+ | |||
+ | struct Bar : BaseClass | ||
+ | { | ||
+ | std::string getName() const override | ||
+ | { | ||
+ | return " | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | struct Foo : BaseClass | ||
+ | { | ||
+ | std::string getName() const override | ||
+ | { | ||
+ | return " | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | std:: | ||
+ | vec.emplace_back(std:: | ||
+ | vec.emplace_back(std:: | ||
+ | |||
+ | for (const auto& v : vec) std::cout << v-> | ||
+ | |||
+ | std::cout << std::endl; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Template=== | ||
+ | |||
+ | '' | ||
+ | |||
+ | <WRAP center round important 60%> | ||
+ | Ce système de masquage ne doit être appliqué que si nécessaire. | ||
+ | |||
+ | [[https:// | ||
+ | </ | ||
+ | |||
+ | |||
+ | Ici, '' | ||
+ | |||
+ | <code cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | class Object | ||
+ | { | ||
+ | | ||
+ | template < | ||
+ | Object(std:: | ||
+ | |||
+ | std::string getName() const | ||
+ | { | ||
+ | return object-> | ||
+ | } | ||
+ | |||
+ | struct Concept | ||
+ | { | ||
+ | virtual ~Concept() {} | ||
+ | virtual std::string getName() const = 0; | ||
+ | }; | ||
+ | |||
+ | template< | ||
+ | struct Model final : Concept | ||
+ | { | ||
+ | Model(std:: | ||
+ | std::string getName() const final | ||
+ | { | ||
+ | return object-> | ||
+ | } | ||
+ | | ||
+ | std:: | ||
+ | }; | ||
+ | |||
+ | std:: | ||
+ | }; | ||
+ | |||
+ | struct Bar | ||
+ | { | ||
+ | std::string getName() const | ||
+ | { | ||
+ | return " | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | struct Foo | ||
+ | { | ||
+ | std::string getName() const | ||
+ | { | ||
+ | return " | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | std:: | ||
+ | vec.emplace_back(std:: | ||
+ | vec.emplace_back(std:: | ||
+ | |||
+ | for (const auto& v : vec) | ||
+ | std::cout << v-> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | [[https:// | ||
=====Hack===== | =====Hack===== | ||
lang/cpp/classes.1589362271.txt.gz · Dernière modification : 2020/05/13 11:31 de root