Domanda

Sto lavorando in un ambiente incorporato (Arduino / AVR ATMega328) e desidero implementare il modello Metodo di fabbrica in C ++. Tuttavia, il compilatore che sto usando (avr-gcc) non supporta la parola chiave new . Esiste un modo per implementare questo modello senza usare new ?

È stato utile?

Soluzione

Poiché il compilatore AVR si basa sul compilatore gcc, è molto probabile che supporti la nuova parola chiave. Qual è esattamente l'errore che stai ricevendo. Immagino sia un errore di collegamento / compilatore sulla falsariga di una funzione indefinita, vale a dire un operatore nuovo. Esiste una differenza tra il nuovo operatore e il nuovo operatore, il primo viene utilizzato per creare oggetti e il secondo viene utilizzato per allocare memoria per gli oggetti. Il nuovo operatore chiama l'operatore new per il tipo di oggetto che viene creato, quindi inizializza la v-table dell'oggetto e chiama i costruttori dell'oggetto. Leggendo questa FAQ si dice che l'operatore new non è definito in le librerie standard. Questo è facile da risolvere, basta definirne uno:

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

e dovrai definire anche un'eliminazione:

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

L'unica cosa da aggiungere è la gestione della memoria, l'allocazione e la liberazione di blocchi di memoria. Questo può essere fatto in modo banale, facendo attenzione a non ostruire alcuna memoria allocata esistente (il codice, i dati statici / globali, lo stack). Dovresti avere due simboli definiti: uno per l'inizio della memoria libera e uno per la fine della memoria libera. È possibile allocare e liberare in modo dinamico qualsiasi pezzo di memoria in questa regione. Dovrai gestire tu stesso questa memoria.

Altri suggerimenti

Se non c'è modo di creare un'istanza di una classe in fase di esecuzione, suppongo che ciò non sia possibile. Tutto quello che puoi fare è pre-allocare alcuni oggetti in fase di compilazione, creare riferimenti ad essi e restituirli quando necessario.

Il quadro generale del metodo Factory è la creazione di oggetti, che significa consumo di memoria heap. Su un sistema incorporato, sei limitato dalla RAM e devi prendere tutte le tue decisioni di progettazione tenendo presente i limiti di memoria. L'ATmega328 ha solo 2 KB di RAM. Consiglio di non utilizzare la memoria allocata dinamicamente in uno spazio così ristretto

Senza conoscere il problema in modo più dettagliato, consiglierei di dichiarare staticamente una manciata di istanze della classe e riutilizzarle in qualche modo. Ciò significa che devi sapere quando e perché i tuoi oggetti vengono creati e - SOLO COME IMPORTANTE - quando e perché terminano; allora devi capire quanti ne devi avere attivi contemporaneamente e quanti è possibile avere attivi contemporaneamente.

!! Dean

Che ne dici di qualcosa del genere?

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

EDIT: ho dimenticato di menzionare, presume che MyClass abbia un operatore di assegnazione.

EDIT2: Un'altra cosa che ho dimenticato - sì, c'è un gotcha (è C ++, ci sono sempre gotcha). Dovrai chiamare manualmente l'tor per l'oggetto, poiché non puoi utilizzare gratuitamente.

Se stai usando factory significa che vuoi un comportamento di associazione dinamica che indica che hai alcune funzioni virtuali. Sebbene, potrebbe essere possibile allocare la memoria per l'oggetto usando malloc () la vtable della classe non verrà impostata correttamente e quindi la chiamata alle funzioni virtuali andrà in crash. Non vedo alcun modo per farlo quando è richiesto il binding dinamico.

Sai fare il malloc? Se è così puoi mallocare il tuo oggetto in quel modo.

Qual è la natura dei tuoi oggetti che vuoi creare dalla Fabbrica?

  • Sono imutabili?
  • La fabbrica intende produrre un insieme limitato di oggetti che possono essere conosciuti in fase di compilazione?

Se la risposta è affermativa a entrambe le domande, puoi allocare staticamente la memoria per il tuo set di oggetti immutabili e lasciare che il metodo factory restituisca i puntatori all'oggetto appropriato.

Questo non funzionerà se la risposta è no a nessuna delle due domande. Anche con questo approccio hai il problema di avere sempre quella memoria allocata.

Un modo in cui ho risolto questo problema in un sistema incorporato con rigidi standard di codifica (dove non ci era permesso usare "nuovo" o "cancella") era creare un array statico dell'oggetto desiderato. Quindi usa i puntatori statici per gli oggetti già allocati, memorizzando questi valori restituiti (usando variabili statiche e / o variabili membro) per la successiva esecuzione dei vari oggetti.

// 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;
    }
}

Si prega di essere avvisati. Questo è tutto a memoria poiché non scrivo C ++ da oltre 8 mesi.

Nota anche: questo ha un grave svantaggio in quanto si sta allocando un sacco di RAM al momento della compilazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top