J'ai un groupe de classes qui héritent toutes des mêmes attributs d'une classe de base commune. La classe de base implémente quelques fonctions virtuelles qui fonctionnent dans des cas généraux, tandis que chaque sous-classe ré-implémente ces fonctions virtuelles pour une variété de cas spéciaux.
Voici la situation : Je veux que la spécificité de ces objets sous-classés soit sacrifiée. Essentiellement, j'aimerais implémenter un objet expend()
qui permet à un objet de perdre son identité de sous-classe et de redevenir une instance de la classe de base avec les comportements généraux mis en œuvre dans la classe de base.
Je dois noter que les classes dérivées n'introduisent pas de variables supplémentaires, donc les classes de base et dérivées devraient avoir la même taille en mémoire.
Je suis prêt à détruire l'ancien objet et à en créer un nouveau, à condition que je puisse créer le nouvel objet à la même adresse mémoire, afin que les pointeurs existants ne soient pas cassés.
La tentative suivante ne fonctionne pas, et produit un comportement apparemment inattendu. Qu'est-ce qui m'échappe ici ?
#include <iostream>
class Base {
public:
virtual void whoami() {
std::cout << "I am Base\n";
}
};
class Derived : public Base {
public:
void whoami() {
std::cout << "I am Derived\n";
}
};
Base* object;
int main() {
object = new Derived; //assign a new Derived class instance
object->whoami(); //this prints "I am Derived"
Base baseObject;
*object = baseObject; //reassign existing object to a different type
object->whoami(); //but it *STILL* prints "I am Derived" (!)
return 0;
}
3 votes
N'oubliez pas que le C++ n'est pas un langage dynamique, une fois qu'il est compilé, tout est fixé.
10 votes
Ce que vous semblez demander est une application du nouveau placement, mais je ne fournirai pas de réponse -- c'est une mauvaise conception IMO.
7 votes
Peut-être que vous pouvez utiliser la panthère de conception de stratégie au lieu d'une hiérarchie de classe
5 votes
@Someprogrammerdude : C'est trop fort. Il y a une raison pour laquelle nous avons quelque chose appelé
dynamic_cast
. S'il est vrai qu'un objet ne change jamais de type, nous pouvons utiliser des expressions de différents types compatibles pour nous référer à cet objet. En particulier, nous pouvons utiliser des classes de base. Ex.Base* p = rand() ? new Derived1 : new Derived2;
. Alors que le statique type dep
est fixé, le dynamique type de*p
ne l'est pas.3 votes
L'erreur dans
*object = baseObject
suggère fortement que vous ne comprenez pas les fondements mêmes de l'héritage et du polymorphisme. Une fois que vous aurez surmonté cela, vous découvrirez probablement une réponse évidente, par exemple que ce que vous vouliez était la composition au lieu de l'héritage ou quelque chose de tout aussi trivial.0 votes
Il semble que ce que vous souhaitez faire est de CASTER votre classe enfant/dérivée dans la classe parent/base. Tant que la classe dérivée a été correctement sous-classée, cela devrait être un casting simple. Est-ce que j'ai raté quelque chose ?
0 votes
@dwk : Voulez-vous dire qu'il est possible de faire cela selon la langue ? Ou bien voulez-vous dire qu'il est possible de faire ceci en pratique même si le langage dit que c'est un comportement non défini ?
0 votes
@ByronJones : Ouaip. Dans ce cas, le casting n'a aucun effet ; même quelque chose comme
((Base*)object)->whoami()
appellera le comportement de la classe dérivée.0 votes
@Mehrdad Je ne voudrais pas dépendre d'un quelconque "accident heureux" de mise en œuvre, ou d'allocations fortuites qui pourraient échouer lors du portage sur ARM. En dehors de cela, je ne comprends pas bien votre distinction entre le langage et la pratique.
1 votes
@Agent_L : une remarque juste mais peut-être tautologique ?
0 votes
@dwk : il y a des choses qui fonctionnent en pratique sur la plupart, sinon tous les compilateurs actuels, mais qui ne sont pas garanties de fonctionner dans le langage. Êtes-vous intéressé par ces choses ?
0 votes
Je me souviens qu'il y avait quelque chose dans les librairies de boost qui faisait cela, dans les usines de remplacement je crois.
0 votes
Le Design Pattern "State" pourrait également être utile, au moins il est décrit par "L'objet semblera changer de classe" dans le livre "Design Patterns".