Retour au cours
QCM sur Héritage, constructeurs et polymorphisme en C++
Appartient au cours : Héritage, constructeurs et polymorphisme en C++
{
"questions": [
{
"question": "Quel est le but principal de l'héritage en programmation orientée objet (POO) ?",
"options": [
{
"text": "Permettre la duplication de code entre classes.",
"why": "L'héritage vise à éviter la duplication de code, pas à la favoriser. Il permet la réutilisation et la spécialisation du code existant.",
"correct": false
},
{
"text": "Réutiliser du code, spécialiser des classes et établir une hiérarchie logique.",
"why": "C'est le but principal de l'héritage : réutiliser le code d'une classe mère, spécialiser les classes filles et organiser les classes dans une hiérarchie logique.",
"correct": true
},
{
"text": "Rendre tous les membres d'une classe mère accessibles à l'extérieur.",
"why": "L'héritage ne modifie pas les règles d'accès des membres d'une classe mère. Les membres `private` restent inaccessibles, même pour les classes filles.",
"correct": false
},
{
"text": "Créer des instances indépendantes sans lien entre elles.",
"why": "L'héritage crée un lien hiérarchique entre les classes (mère et fille), ce qui est l'opposé de la création d'instances indépendantes.",
"correct": false
}
]
},
{
"question": "Dans le contexte de l'héritage, que signifie un membre `protected` dans une classe mère ?",
"options": [
{
"text": "Il est accessible uniquement par la classe mère et inaccessible partout ailleurs.",
"why": "Un membre `protected` est accessible par la classe mère **et** par les classes filles, mais pas de l'extérieur.",
"correct": false
},
{
"text": "Il est accessible par la classe mère, les classes filles, et de l'extérieur.",
"why": "Un membre `protected` n'est **pas** accessible de l'extérieur. Seules la classe mère et les classes filles y ont accès.",
"correct": false
},
{
"text": "Il est accessible par la classe mère et les classes filles, mais pas de l'extérieur.",
"why": "C'est la définition exacte d'un membre `protected` dans le contexte de l'héritage.",
"correct": true
},
{
"text": "Il est automatiquement converti en `public` dans les classes filles.",
"why": "Le niveau de protection d'un membre `protected` dépend du type d'héritage (`public`, `protected` ou `private`), mais il n'est pas automatiquement converti en `public`.",
"correct": false
}
]
},
{
"question": "Quel est l'ordre d'appel des constructeurs lors de la création d'un objet d'une classe fille ?",
"options": [
{
"text": "Le constructeur de la classe fille est appelé en premier, suivi de celui de la classe mère.",
"why": "L'ordre est inverse : le constructeur de la classe mère est appelé en premier, suivi de celui de la classe fille. Cela permet d'initialiser les attributs hérités avant ceux de la classe fille.",
"correct": false
},
{
"text": "Le constructeur de la classe mère est appelé en premier, suivi de celui de la classe fille.",
"why": "C'est l'ordre correct. Les constructeurs sont appelés de manière hiérarchique, de la classe la plus générale à la plus spécifique.",
"correct": true
},
{
"text": "Les constructeurs de la classe mère et de la classe fille sont appelés en parallèle.",
"why": "Les constructeurs ne sont pas appelés en parallèle. Ils sont exécutés séquentiellement, en commençant par la classe mère.",
"correct": false
},
{
"text": "Seul le constructeur de la classe fille est appelé, car il hérite de tous les attributs de la classe mère.",
"why": "Le constructeur de la classe mère est toujours appelé pour initialiser les attributs hérités, même si la classe fille définit ses propres attributs.",
"correct": false
}
]
},
{
"question": "Que se passe-t-il lorsqu'une méthode de la classe fille a le même nom qu'une méthode de la classe mère ?",
"options": [
{
"text": "La méthode de la classe mère est appelée par défaut, sauf si elle est déclarée `virtual`.",
"why": "C'est l'inverse : la méthode de la classe fille masque celle de la classe mère, sauf si la méthode mère est déclarée `virtual` et qu'on utilise un pointeur ou une référence de type mère.",
"correct": false
},
{
"text": "La méthode de la classe fille masque celle de la classe mère, sauf si la méthode mère est déclarée `virtual`.",
"why": "C'est le phénomène de masquage : la méthode de la classe fille prend le pas sur celle de la classe mère, sauf dans le cas du polymorphisme avec des méthodes `virtual`.",
"correct": true
},
{
"text": "Les deux méthodes sont fusionnées en une seule méthode qui combine leurs comportements.",
"why": "Il n'y a pas de fusion automatique des méthodes. La méthode de la classe fille masque celle de la classe mère, sauf si on appelle explicitement la méthode mère avec `ClasseMere::methode()`.",
"correct": false
},
{
"text": "La méthode de la classe mère est supprimée et remplacée par celle de la classe fille.",
"why": "La méthode de la classe mère n'est pas supprimée. Elle est simplement masquée et peut être appelée explicitement si nécessaire.",
"correct": false
}
]
},
{
"question": "Pourquoi déclare-t-on une méthode comme `virtual` dans une classe mère ?",
"options": [
{
"text": "Pour permettre à la méthode d'être appelée même si elle est masquée par une méthode de la classe fille.",
"why": "Une méthode `virtual` permet le polymorphisme : l'appel de la méthode dépend du type réel de l'objet (et non du type statique du pointeur ou de la référence). Cela ne concerne pas directement le masquage.",
"correct": false
},
{
"text": "Pour que l'appel de la méthode dépende du type réel de l'objet pointé, et non du type statique du pointeur.",
"why": "C'est la raison principale de l'utilisation de `virtual`. Cela permet le polymorphisme, où le comportement de la méthode s'adapte au type réel de l'objet.",
"correct": true
},
{
"text": "Pour rendre la méthode accessible depuis l'extérieur de la classe.",
"why": "Le mot-clé `virtual` n'a aucun impact sur l'accessibilité d'une méthode. Il est utilisé pour activer le polymorphisme.",
"correct": false
},
{
"text": "Pour empêcher la méthode d'être redéfinie dans les classes filles.",
"why": "C'est l'inverse : `virtual` permet (et encourage) la redéfinition de la méthode dans les classes filles pour activer le polymorphisme.",
"correct": false
}
]
},
{
"question": "Quel est l'avantage principal des itérateurs en C++ ?",
"options": [
{
"text": "Ils permettent de parcourir uniquement les conteneurs de type `vector`.",
"why": "Les itérateurs sont conçus pour être génériques et fonctionnent avec **tous** les conteneurs de la STL, pas seulement les `vector`.",
"correct": false
},
{
"text": "Ils offrent une flexibilité pour parcourir tous les conteneurs de la STL et interagir précisément avec leurs éléments.",
"why": "C'est l'avantage principal des itérateurs : ils permettent de parcourir et manipuler les éléments de n'importe quel conteneur STL de manière uniforme et flexible.",
"correct": true
},
{
"text": "Ils remplacent complètement les boucles `for` traditionnelles.",
"why": "Les itérateurs ne remplacent pas les boucles `for`, mais ils offrent une alternative plus flexible et générique pour parcourir les conteneurs.",
"correct": false
},
{
"text": "Ils sont utilisés uniquement pour trier les éléments d'un conteneur.",
"why": "Les itérateurs ne sont pas limités au tri. Ils permettent de parcourir, accéder et manipuler les éléments d'un conteneur, et sont utilisés par de nombreuses fonctions de la bibliothèque `<algorithm>`.",
"correct": false
}
]
},
{
"question": "Quelle est la différence entre un conteneur séquentiel et un conteneur associatif dans la STL ?",
"options": [
{
"text": "Les conteneurs séquentiels stockent des éléments dans un ordre défini par l'utilisateur, tandis que les conteneurs associatifs stockent des éléments sans ordre particulier.",
"why": "Les conteneurs associatifs stockent les éléments selon un ordre défini par une clé (par exemple, triés par ordre croissant pour un `set`), pas sans ordre particulier.",
"correct": false
},
{
"text": "Les conteneurs séquentiels stockent des éléments dans un ordre défini par l'utilisateur, tandis que les conteneurs associatifs stockent des éléments selon une clé (ex: triés ou par paires clé/valeur).",
"why": "C'est la différence fondamentale : les conteneurs séquentiels (`vector`, `list`) maintiennent l'ordre d'insertion, tandis que les conteneurs associatifs (`set`, `map`) organisent les éléments selon une clé.",
"correct": true
},
{
"text": "Les conteneurs séquentiels sont plus rapides pour les recherches que les conteneurs associatifs.",
"why": "C'est l'inverse : les conteneurs associatifs (`set`, `map`) sont optimisés pour les recherches rapides, tandis que les conteneurs séquentiels (`vector`, `list`) ne le sont pas.",
"correct": false
},
{
"text": "Les conteneurs séquentiels ne peuvent pas être modifiés après leur création, contrairement aux conteneurs associatifs.",
"why": "Les deux types de conteneurs peuvent être modifiés après leur création (ajout, suppression d'éléments).",
"correct": false
}
]
},
{
"question": "Dans quel cas utiliserait-on un héritage de type `private` ?",
"options": [
{
"text": "Pour rendre tous les membres `public` et `protected` de la classe mère accessibles comme `public` dans la classe fille.",
"why": "Un héritage `private` convertit tous les membres `public` et `protected` de la classe mère en `private` dans la classe fille, pas en `public`.",
"correct": false
},
{
"text": "Pour masquer complètement l'héritage et rendre tous les membres hérités `private` dans la classe fille, même s'ils étaient `public` ou `protected` dans la classe mère.",
"why": "C'est le rôle de l'héritage `private` : il convertit tous les membres hérités (`public` et `protected`) en `private` dans la classe fille, masquant ainsi l'héritage de l'extérieur.",
"correct": true
},
{
"text": "Pour permettre à la classe fille d'accéder aux membres `private` de la classe mère.",
"why": "Aucun type d'héritage ne permet d'accéder aux membres `private` d'une classe mère. Seuls les membres `protected` et `public` sont accessibles, selon le type d'héritage.",
"correct": false
},
{
"text": "Pour créer une relation « est-un » entre la classe mère et la classe fille, visible de l'extérieur.",
"why": "L'héritage `private` masque la relation « est-un » de l'extérieur. Seuls les héritages `public` et `protected` préservent cette relation de manière visible.",
"correct": false
}
]
},
{
"question": "Quelle est la bonne pratique lorsqu'on redéfinit une méthode dans une classe fille pour personnaliser son comportement ?",
"options": [
{
"text": "Ignorer complètement la méthode de la classe mère et écrire une nouvelle implémentation.",
"why": "Ignorer la méthode de la classe mère peut entraîner de la duplication de code et rendre le code moins maintenable. Il est préférable d'appeler la méthode mère avant d'ajouter des spécificités.",
"correct": false
},
{
"text": "Appeler la méthode de la classe mère (`ClasseMere::methode()`) puis ajouter les spécificités de la classe fille pour éviter la duplication de code.",
"why": "C'est la bonne pratique : appeler la méthode mère permet de réutiliser son comportement, puis d'ajouter les spécificités de la classe fille.",
"correct": true
},
{
"text": "Déclarer la méthode de la classe mère comme `private` pour forcer la classe fille à redéfinir complètement la méthode.",
"why": "Déclarer la méthode mère comme `private` l'empêcherait d'être accessible dans la classe fille, ce qui n'est pas souhaitable pour la réutilisation de code.",
"correct": false
},
{
"text": "Utiliser uniquement des méthodes `virtual` pour éviter d'avoir à appeler explicitement la méthode mère.",
"why": "Les méthodes `virtual` permettent le polymorphisme, mais ne dispensent pas d'appeler explicitement la méthode mère si on souhaite réutiliser son comportement dans la classe fille.",
"correct": false
}
]
},
{
"question": "Quel est l'intérêt d'utiliser la bibliothèque `<algorithm>` avec des itérateurs ?",
"options": [
{
"text": "Elle permet de créer des conteneurs personnalisés qui ne sont pas disponibles dans la STL.",
"why": "La bibliothèque `<algorithm>` ne crée pas de conteneurs. Elle fournit des fonctions génériques pour manipuler les éléments des conteneurs existants (tri, recherche, etc.).",
"correct": false
},
{
"text": "Elle offre des fonctions génériques (comme `sort`, `find`, `count`) qui peuvent être utilisées avec n'importe quel conteneur via des itérateurs.",
"why": "C'est l'intérêt principal de `<algorithm>` : elle fournit des fonctions génériques qui fonctionnent avec tous les conteneurs de la STL grâce aux itérateurs.",
"correct": true
},
{
"text": "Elle remplace les itérateurs par des boucles `for` traditionnelles pour simplifier le code.",
"why": "La bibliothèque `<algorithm>` utilise les itérateurs pour fonctionner, elle ne les remplace pas par des boucles `for`.",
"correct": false
},
{
"text": "Elle permet de convertir automatiquement les conteneurs séquentiels en conteneurs associatifs.",
"why": "La bibliothèque `<algorithm>` ne convertit pas les conteneurs. Elle fournit des outils pour manipuler leurs éléments.",
"correct": false
}
]
}
]
}