Question

J'ai une classe de base que je veux ressembler à ceci:

class B
{
    // should look like: int I() { return someConst; }
    virtual int I() = 0;
    public B() { something(I()); }
}

Le point étant de forcer les classes dérivées pour remplacer I et le forcer à être appelée lorsque chaque objet est construit. Cela se habitue à faire un peu de comptabilité et j'ai besoin de savoir quel type d'objet est en cours de construction (mais je traite autrement l'objet courant comme la classe de base).

Cela ne fonctionne pas parce que C ++ ne vous laissera pas appeler une fonction virtuelle abstraite du constructeur.

Y at-il un moyen d'obtenir le même effet?


Basé sur ce lien il semblerait que la réponse est il n'y a pas moyen d'obtenir ce que je veux. Mais ce qu'il dit est:

  

La réponse courte est: non. Une classe de base ne sait rien de ce que la classe il est dérivé et c'est une bonne chose, aussi. [...] C'est, l'objet ne devienne pas officiellement une instance de Derived1 jusqu'à ce que le constructeur Derived1 :: Derived1 commence.

Cependant, dans mon cas, je ne veux pas savoir ce que est mais ce qu'il devenir . En fait, je ne me soucie même pas ce que je reviens aussi longtemps que je l'utilisateur peut (après le fait) la carte à une classe. Donc, je pourrais même utiliser quelque chose comme un pointeur de retour et sortir avec elle.

(maintenant à la lecture de ce lien)

Était-ce utile?

La solution

Vous ne pouvez pas appeler des méthodes virtuelles à partir du constructeur (ou pour être plus précis, vous peut les appeler, mais vous finirez par appeler la fonction membre de la classe en cours de construction). , le problème est que l'objet dérivé n'existe pas encore à ce moment-là. Il y a très peu que vous pouvez faire à ce sujet, appeler des méthodes virtuelles à partir du constructeur est tout simplement polymorphically hors de question.

Vous devriez revoir votre conception - en passant la constante comme argument au constructeur, par exemple

.
class B
{
public:
    explicit B(int i)
    {
        something(i);
    }
};

Voir C ++ faq plus . Si vous vraiment veulent appeler des fonctions virtuelles pendant la construction, lire .

Autres conseils

Peut-être utiliser une méthode de fabrication statique sur chaque type dérivé? Ceci est la façon habituelle pour construire des objets exotiques (lire: ceux qui ont des exigences très spécifiques d'initialisation). .NET, que je suis venu à apprécier

class Base
{
  protected Base(int i)
  {
    // do stuff with i
  }
}

class Derived : public Base
{
  private Derived(int i)
    : Base(i)
  {
  }

  public Derived Create()
  {
    return new Derived(someConstantForThisDerivedType);
  }
}

Appel de méthodes virtuelles dans les constructeurs de base est généralement désapprouvé, comme vous ne pouvez jamais être certain du comportement d'une méthode particulière, et (comme quelqu'un d'autre a déjà indiqué) les constructeurs dérivés n'ont encore été appelé.

Cela ne fonctionne pas comme la classe dérivée n'existe pas encore lorsque le constructeur de la classe de base est exécutée:

class Base
{
public:
    Base()
    {
        // Will call Base::I and not Derived::I because
        // Derived does not yet exist.
        something(I());
    }

    virtual ~Base() = 0
    {
    }

    virtual int I() const = 0;
};

class Derived : public Base
{
public:
    Derived()
     : Base()
    {
    }

    virtual ~Derived()
    {
    }

    virtual int I() const
    {
        return 42;
    }
};

vous pouvez ajouter les arguments lieu au constructeur de la classe de base:

class Base
{
public:
    explicit Base(int i)
    {
        something(i);
    }

    virtual ~Base() = 0
    {
    }
};

class Derived : public Base
{
public:
    Derived()
     : Base(42)
    {
    }

    virtual ~Derived()
    {
    }
};

Ou si vous êtes vraiment friands de POO, vous pouvez également créer deux classes supplémentaires:

class Base
{
public:
    class BaseConstructorArgs
    {
    public:
        virtual ~BaseConstructorArgs() = 0
        {
        }

        virtual int I() const = 0;
    };

    explicit Base(const BaseConstructorArgs& args)
    {
        something(args.I());
    }

    virtual ~Base() = 0
    {
    }
};

class Derived : public Base
{
public:
    class DerivedConstructorArgs : public BaseConstructorArgs
    {
    public:
        virtual ~DerivedConstructorArgs()
        {
        }

        virtual int I() const
        {
            return 42;
        }
    };

    Derived()
     : Base(DerivedConstructorArgs())
    {
    }

    virtual ~Derived()
    {
    }
};

Qu'est-ce que vous avez besoin est construction en deux phases . Utilisez le traitement du programmeur Universal: Ajoutez une autre couche d'indirection.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top