20 votes

Éviter de copier tous les constructeurs dans les sous-classes

Une classe de base a donc plusieurs constructeurs :

sf::Sprite()
sf::Sprite(const Texture& texture)
sf::Sprite(const Texture& texture, const IntRect& rectangle)

Et je sous-classe cette classe plusieurs fois :

class Sub : public sf::Sprite {
    public:
        Sub() : sf::Sprite() {};
        Sub(const Texture& texture) : sf::Sprite(texture) {};
        Sub(const Texture& texture, const IntRect& rectangle) : sf::Sprite(texture, rectangle) {};

        // My subclass specific code
};

Comme vous le voyez, je dois répéter ces trois constructeurs pour chaque sous-classe. Existe-t-il un moyen d'éviter cela, puisque les constructeurs ne font généralement rien de spécial ? Parfois J'ai besoin un peu de Cependant, l'initialisation de la classe est spécifique, il n'est donc pas toujours possible de tout copier directement.

35voto

songyuanyao Points 2265

Vous pouvez y parvenir en hériter des constructeurs (depuis C++11).

Si la déclaration d'utilisation fait référence à un constructeur d'une base directe de la classe en cours de définition (par ex. using Base::Base; ), tous les constructeurs de cette base (ignorant l'accès aux membres) sont rendus visibles à la résolution de surcharge lors de l'initialisation de la classe dérivée.

par exemple

class Sub : public sf::Sprite {
    public:
        using sf::Sprite::Sprite;

        // My subclass specific code
};

Si les constructeurs hérités sont utilisés pour initialiser un fichier de type Sub El sf::Sprite est initialisé à l'aide du constructeur hérité, et tous les autres membres de l'objet Sub sont initialisés comme par le constructeur par défaut.

Si des cas particuliers doivent être traités, vous pouvez toujours définir le(s) constructeur(s) dans le fichier Sub le constructeur hérité avec la même signature sera caché.

Comme pour les déclarations d'utilisation de toute autre fonction membre non statique, si un constructeur hérité correspond à la signature de l'un des constructeurs de Derived, il est caché de la recherche par la version trouvée dans Derived.

15voto

Sebastian Stern Points 592

Vous pouvez utiliser le using pour hériter du constructeur de votre classe de base, à l'exception des constructeurs spéciaux (default, copy, move). Pour raccourcir votre constructeur par défaut, utilisez simplement = default . Si vous voulez une initialisation spécifique à une classe, vous pouvez simplement écrire à nouveau le constructeur, comme vous le faites maintenant.

class Sub : public sf::Sprite {
    public:
        Sub() = default;
        using sf::Sprite::Sprite;

        Sub(const Texture& texture) 
        {
           // your custom code.
        };

        // My subclass specific code
};

7voto

Walter Points 7554

Si vous pouvez simplement "hériter" du constructeur, c'est-à-dire en avoir un avec exactement les mêmes arguments, utilisez simplement using comme expliqué dans les autres réponses. Cependant, si votre derived possède des arguments supplémentaires et/ou requiert initialisation de certaines classes spécifiques vous pouvez utiliser un modèle variadique.

struct base
{
  base(int);
  base(std::string const&);
  base(some_type const&);
  base(std::string const&, some_type const&);
  /* ... */
};

struct derived : base
{
  template<typename...Args>
  derived(some_other_type const&x, Args&&...args)
  : base(std::forward<Args>(args)...)
  , private_datum(x)
  {
    construction_details();          // class-specific initialisation
  }
private:
  some_other_type private_datum;
  void construction_details();       // implemented in source code
};

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X