Allocation d’un object de type classe abstraite ‘CObject’

Je veux implémenter CWindow et d’autres éléments en utilisant le polymorphism et la classe abstraite CObject. Mais j’ai eu une erreur ‘Allocation d’un object de type classe abstraite’ CObject ‘.

class CObject { public: CObject ( const int id, const ssortingng &title, const CRect &pos ): m_id(id),m_title(title),m_pos(make_unique(pos)) { } virtual void print ( ostream &os ) const = 0; virtual void add ( const CObject &src ){ m_src.push_back(make_unique(src)); //->here the problem } friend ostream & operator << (ostream &os, const CObject &src ){ src.print(os); return os; } protected: int m_id; string m_title; unique_ptr m_pos; vector< unique_ptr > m_src; }; 

Par exemple, je veux créer un bouton, puis l’append à la fenêtre CWindow (dans la fonction principale). La fenêtre a une position absolue, mais d’autres parties de la fenêtre dépendent de CWindow. Ensuite, je souhaite redimensionner la fenêtre et tous les éléments seront automatiquement redimensionnés. Je dois donc stocker toutes les données relatives aux sous-éléments.

 class CWindow : public CObject { public: CWindow ( const ssortingng & title, const CRect & absPos ): CObject(0,title,absPos) { }; virtual void print ( ostream &os ) const{ os << "CWindow"; }; CWindow & Add ( const CObject &src ){ add(src); return *this; } }; class CButton : public CObject { public: CButton ( int id, const CRect &relPos, const string &name ): CObject(id,name,relPos) { } }; 

Exemple de la fonction principale

  int main ( void ) { CWindow a ( "Sample window", CRect ( 10, 10, 600, 480 ) ); a . Add ( CButton ( 1, CRect ( 0.1, 0.8, 0.3, 0.1 ), "Ok" ) ) . Add ( CButton ( 2, CRect ( 0.6, 0.8, 0.3, 0.1 ), "Cancel" ) ); } 

CObject est une classe abstraite, car print() est abstraite. En tant que tel, vous NE POUVEZ PAS créer d’instances de CObject directement. Vous ne pouvez instancier que des classes dérivées concrètes implémentant print() .

L’appel de std::make_unique(...) tente d’instancier CObject lui-même, c’est pourquoi il échoue dans votre code. Vous devez plutôt spécifier une classe dérivée, par exemple: std::make_unique(...) .

Cependant, la méthode add() vous avez montrée ne fonctionnera pas, pour plusieurs raisons:

  • il n’a aucun moyen de savoir si le CObject transmis CObject été alloué en mémoire automatique ou dynamic. L’exemple main() vous avez montré crée des objects dans la mémoire automatique, mais le programme de suppression par défaut de std::unique_ptr ( std::delete ) requirejs plutôt de la mémoire dynamic.

  • l’appelant n’a aucun moyen de spécifier le type correct à transmettre au paramètre de modèle T de std::make_unique() .

  • Aucune de vos classes dérivées n’a de constructeur qui CObject un CObject en entrée. Vous ne pouvez donc pas spécifier le CObject transmis dans le paramètre args de std::make_unique() .

Vous devez changer add() pour utiliser plutôt std::unique_ptr , puis vous pourrez simplement std::move() le dans votre vector , par exemple:

 virtual void add(std::unique_ptr src) { m_src.push_back(std::move(src)); } 

Laissez l’appelant gérer la construction de l’object souhaité, add() prend possession:

 int main() { CWindow a("Sample window", CRect(10, 10, 600, 480)); a.add(std::make_unique(1, CRect(0.1, 0.8, 0.3, 0.1), "Ok")); a.add(std::make_unique(2, CRect(0.6, 0.8, 0.3, 0.1), "Cancel")); } 

Sinon, si vous voulez que add() appelle std::make_unique() au nom de l’appelant, vous aurez besoin de quelque chose de plus semblable à ceci:

 template void add(Args&&... args) { m_src.push_back(std::make_unique(args)); } ... int main() { CWindow a("Sample window", CRect(10, 10, 600, 480)); a.add(1, CRect(0.1, 0.8, 0.3, 0.1), "Ok"); a.add(2, CRect(0.6, 0.8, 0.3, 0.1), "Cancel"); } 

Vous devez implémenter une méthode print dans une classe CObject . Par exemple.:

 virtual void print ( ostream &os ) const {};