Question

Je travaille dans un environnement embarqué (Arduino / AVR ATMega328) et souhaite implémenter le modèle Factory Method en C ++. Cependant, le compilateur que j'utilise (avr-gcc) ne prend pas en charge le mot clé new . Existe-t-il un moyen d'implémenter ce modèle sans utiliser new ?

Était-ce utile?

La solution

Etant donné que le compilateur AVR est basé sur le compilateur gcc, il est très probable qu’il supporte le nouveau mot-clé. Quelle est exactement l'erreur que vous obtenez. J'imagine que c'est une erreur de lien / compilateur dans le sens d'une fonction non définie, à savoir opérateur new. Il existe une différence entre l'opérateur new et l'opérateur new. Le premier est utilisé pour créer des objets et le dernier est utilisé pour allouer de la mémoire aux objets. L'opérateur new appelle l'opérateur new pour le type d'objet créé, puis initialise la table v de l'objet et appelle les constructeurs de l'objet. La lecture de cette FAQ indique que l'opérateur new n'est pas défini dans les bibliothèques standard. C’est facile à corriger, il suffit d’en définir un:

void *operator new (size_t size)
{
  return some allocated memory big enough to hold size bytes
}

et vous devrez également définir une suppression:

void operator delete (void *memory)
{
   free the memory
}

La seule chose à ajouter est la gestion de la mémoire, l’allocation et la libération de blocs de mémoire. Cela peut être fait de manière triviale, en prenant soin de ne pas surcharger la mémoire allouée existante (le code, les données statiques / globales, la pile). Vous devez définir deux symboles: un pour le début de la mémoire libre et un pour la fin de la mémoire libre. Vous pouvez allouer et libérer de manière dynamique tout bloc de mémoire dans cette région. Vous devrez gérer vous-même cette mémoire.

Autres conseils

S'il n'y a aucun moyen d'instancier une classe au moment de l'exécution, je suppose que ce n'est pas possible. Tout ce que vous pouvez faire est de pré-allouer certains objets au moment de la compilation, de créer des références et de les renvoyer au besoin.

La vue d'ensemble de la méthode d'usine est la création d'objet, ce qui signifie la consommation de mémoire en tas. Sur un système embarqué, vous êtes limité par la RAM et devez prendre toutes vos décisions de conception en tenant compte de vos limites de mémoire. L'ATmega328 ne dispose que de 2 Ko de RAM. Je recommande de ne pas utiliser de mémoire allouée dynamiquement dans un espace aussi restreint.

Sans connaître votre problème de manière plus détaillée, je vous recommanderais de déclarer de manière statique une poignée d'instances de la classe et de réutiliser ces instances d'une manière ou d'une autre. Cela signifie que vous devez savoir quand et pourquoi vos objets sont créés et - JUST AS IMPORTANT - quand et pourquoi ils se terminent; vous devez ensuite déterminer combien il vous faut d’être actif à la fois et combien il est possible d’être actif à la fois.

!! Dean

Qu'en est-il de quelque chose comme ça?

MyClass *objp = (MyClass*)malloc(sizeof(MyClass));
*objp = MyClass();  // or any other c'tor

EDIT: vous avez oublié de mentionner, cela suppose que MyClass a un opérateur d'affectation.

EDIT2: Une autre chose que j'ai oubliée - oui, il y a un piège (c'est du C ++, il y a toujours des pièges). Vous devrez appeler manuellement d'tor pour l'objet, car vous ne pouvez pas utiliser gratuitement.

Si vous utilisez factory, cela signifie que vous souhaitez un comportement de liaison dynamique indiquant que vous disposez de certaines fonctions virtuelles. Bien qu'il soit possible d'allouer la mémoire pour l'objet à l'aide de malloc (), la table virtuelle de la classe ne sera pas configurée correctement et, par conséquent, l'appel aux fonctions virtuelles se bloquera. Je ne vois aucun moyen de faire cela lorsqu'une liaison dynamique est requise.

Pouvez-vous faire malloc? Si c'est le cas, vous pouvez malloc votre objet de cette façon.

De plus, quelle est la nature de vos objets que vous souhaitez créer à partir de la fabrique?

  • Sont-ils imuables?
  • L'usine est-elle uniquement destinée à produire un ensemble limité d'objets pouvant être connus lors de la compilation?

Si la réponse à ces deux questions est affirmative, vous pouvez allouer de manière statique la mémoire à votre ensemble d'objets immuables et laisser la méthode d'usine renvoyer les pointeurs sur l'objet approprié.

Cela ne fonctionnera pas si la réponse est non à l'une ou l'autre des questions. Aussi, avec cette approche, vous avez le problème de toujours avoir cette mémoire allouée.

Une façon de résoudre ce problème dans un système embarqué avec des normes de codage strictes (nous n'étions pas autorisés à utiliser "nouveau" ou "supprimer") consistait à créer un tableau statique de l'objet souhaité. Ensuite, utilisez des pointeurs statiques vers les objets déjà alloués, en stockant ces valeurs renvoyées (à l'aide de variables statiques et / ou de variables membres) pour une exécution ultérieure des différents objets.

// Class File ---------------------------------------------------
class MyObject {
    public:
        MyObject* getObject();

    private:
        const int MAX_POSSIBLE_COUNT_OF_OBJECTS = 10;
        static MyObject allocatedObjects[MAX_POSSIBLE_COUNT_OF_OBJECTS];

        static allocatedObjectIndex = 0;
};

// Implementation File ------------------------------------------

// Instantiate a static array of your objects.
static MyObject::allocatedObject[MAX_POSSIBLE_COUNT_OF_OBJECTS];

// Your method to return already created objects.
MyObject* MyObject::getObject() {

    if (allocatedObjectIndex < (MAX_POSSIBLE_COUNT_OF_OBJECTS - 1)) {
        return allocatedObjects[allocatedObjectIndex++];
    } else {
        // Log error if possible
        return NULL;
    }
}

S'il vous plaît être prévenu. Tout cela vient de la mémoire, car je n’ai écrit aucun langage C ++ depuis plus de 8 mois.

Veuillez également noter: cela présente un inconvénient majeur, en ce sens que vous allouez une quantité de mémoire RAM au moment de la compilation.

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