Instanciation de l’interface c ++ en tant que classe enfant

J’ai une interface, appelons-la Creature , qui a des fonctions virtuelles qui la rendent abstraite.

J’ai des classes enfants de cette interface telles que Dog , Cat et Pig .

Le compilateur ne semble pas aimer la ligne suivante car il est impossible de déclarer une variable comme étant de type abstrait Creature .

 Creature thing = Dog(); 

Je sais que je ne peux pas instancier des interfaces, etc., mais il ne s’agit que d’un Dog déclaré en tant que Creature .

J’ai besoin d’un moyen de faire en sorte qu’une déclaration fonctionne pour tous les enfants (par exemple, être capable de mettre Dog() , Cat() ou Pig()Dog() est dans la ligne ci-dessus).

Est-ce que cela peut être fait en c ++ ou est-ce que j’utilise mal l’inheritance et les interfaces complètement?

Les types d’object eux-mêmes ne sont pas polymorphes en C ++. La ligne que vous avez indiquée déclare un object Creature , puis tente de l’initialiser avec un object Dog . Si la Creature n’était pas abstraite, cela entraînerait un découpage – la thing ne serait plus un Dog , ce serait simplement une Creature . Comme il est abstrait, vous ne pouvez tout simplement pas avoir d’object Creature .

Vous devez utiliser des pointeurs ou des références pour le comportement polymorphe. Considérons par exemple:

 Creature* thing = new Dog(); 

Vous pouvez maintenant déréférencer quelque thing et l’utiliser en tant que Creature , même si son type dynamic est Dog . Cependant, l’utilisation de pointeurs bruts comme celui-ci n’est généralement pas recommandée, car vous devez vous assurer manuellement que l’object est delete d à un moment donné. La propriété peut devenir déroutante. Votre meilleur choix est de le placer dans un pointeur intelligent, tel que:

 std::unique_ptr thing(new Dog()); // or std::make_unique when we have it 

Ici, j’ai présenté std::unique_ptr , mais le choix du pointeur intelligent dépendra de la sémantique de propriété de cet object. std::shared_ptr est une alternative courante.

Pour démontrer le polymorphism avec des références:

 Dog dog; Creature& thing = dog; // Can now use dog as a Creature 

En C ++, vous devez prendre conscience de la différence entre la sémantique de valeur et celle de référence. Dans les langages interprétatifs, vous avez tendance à ne traiter que la sémantique de référence (à l’exception de certains cas étranges avec de vieux objects de données qui possèdent une sémantique de valeur mais en plus du point).

En C ++, tous les objects sont des valeurs. Par exemple, un object ne peut jamais être null . Cela implique que la déclaration spécifie les exigences de stockage. Considérer ce qui suit

 struct creature { }; struct dog : public creature { float cuteness; }; 

L’obligation de stockage pour un chien est différente de celle d’une créature, même si vous autorisez la conversion, cela entraînerait un découpage en tranches. Par exemple, fido va-t-il aboyer ou se taire? #comprendre

 class creature { public: virtual void speak() { std::cout << "..." << std::endl; } }; class dog : public creature { public: virtual void speak() { std::cout << "woof!" << std::endl; } }; int main(int argc, const char *argv[]) { creature fido; fido = dog(); fido.speak(); return 0; } 

Cependant, si vous aviez simplement un pointeur ou une référence à l'object, le problème est différent. Par pointeur.

 creature* fido = new dog(); fido->speak(); delete fido; 

Par référence.

 dog fido; creature& c = fido; c.speak(); 

Au-delà de la scope de cette question, mais éventuellement d'un pointeur intelligent.

 std::unique_ptr fido(new dog);