Pergunta

Eu estou trabalhando em um ambiente incorporado (Arduino / AVR ATMega328) e deseja implementar o padrão Factory Method em C ++. No entanto, o compilador que estou usando (avr-gcc) não suporta a palavra-chave new. Existe uma maneira de implementar esse padrão sem usar new?

Foi útil?

Solução

Uma vez que o compilador AVR é ??baseado no compilador gcc, é muito provável para suportar a nova palavra-chave. O que exatamente é o erro que você está recebendo. Eu estou supondo que é um erro de link / compilador ao longo das linhas de uma função indefinida, ou seja, o operador novo. Há uma diferença entre o novo operador e operador de novo, a primeira é usada para criar objetos e este último é usado para alocar memória para objetos. O novo operador de chamadas novo operador para o tipo de objeto que está sendo criado, em seguida, inicializa v-tabela do objeto e chama construtores do objeto. A leitura deste FAQ diz que novo operador não está definido no as bibliotecas padrão. Isso é fácil de resolver, basta definir um:

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

e você precisa definir uma exclusão, bem como:

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

A única coisa a acrescentar é o gerenciamento de memória, a alocação e liberação de blocos de memória. Isso pode ser feito trivialmente, tomando cuidado para não espancar qualquer memória existente alocado (o código, / global de dados estática, a pilha). Você deve ter dois símbolos definidos - um para o início da memória livre e outro para o final da memória livre. Você pode alocar dinamicamente e libertar qualquer pedaço de memória na região. Você vai precisar para gerenciar essa memória si mesmo.

Outras dicas

Se não há nenhuma maneira para instanciar uma classe em tempo de execução, acho que isso não é possível. Tudo o que você poderia fazer é pré-alocar alguns objetos em tempo de compilação, criar referências a eles e devolvê-los quando necessário.

A grande imagem do Factory Method é a criação do objeto, o que significa que o consumo de memória heap. Em um sistema embarcado, você está limitado pela RAM e precisa fazer todas as suas decisões de design com os seus limites de memória em mente. O ATmega328 tem apenas 2 KB de RAM. Eu recomendaria contra o uso de memória alocada dinamicamente em um espaço tão apertado.

Sem saber o seu problema com mais detalhes, eu recomendaria estaticamente declarar um punhado de instâncias da classe e re-uso dessas instâncias de alguma forma. Isto significa que você precisa saber quando e por que os objetos são criados e - tão importante - quando e por que eles acabam; então você precisa descobrir quantos você precisa ter ativos de uma só vez e quantos é possível ter ativos ao mesmo tempo.

!! Dean

O que sobre algo assim?

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

EDIT:. Esqueci de mencionar, ele assume MyClass tem um operador de atribuição

EDIT2: Outra coisa que eu esqueci - sim, há uma pegadinha (é C ++, há sempre gotchas). Você vai ter que chamar o d'tor manualmente para o objeto, desde que você não pode usar gratuitamente.

Se você estiver usando meios de fábrica que você quer um comportamento de ligação dinâmica que indica que você tem algumas funções virtuais. Embora, pode ser possível alocar a memória para o objeto usando malloc () o vtable da classe não será configurado corretamente e, portanto, a chamada para funções virtuais irá falhar. Eu não vejo qualquer maneira de fazer isso quando a ligação é necessária dinâmica.

Você pode fazer malloc? Se assim você pode malloc seu objeto dessa forma.

Além disso, qual é a natureza de seus objetos que você deseja criar a partir do Factory?

  • São imutable?
  • é a fábrica só se destina a produzir um conjunto limitado de objetos que pode ser conhecido em tempo de compilação?

Se a resposta for sim para as duas perguntas, você pode estaticamente alocar a memória para o conjunto de objetos imutáveis ??e deixar os ponteiros método de fábrica de retorno para o objeto apropriado.

Isso não vai funcionar se a resposta não é para qualquer pergunta. Também wuth essa abordagem, você tem o problema de ter sempre que a memória alocada.

A maneira que eu tenho resolvido este problema em um sistema embarcado com padrões de codificação estritas (onde nós não foram autorizados a usar "novo" ou "delete") era criar uma matriz estática do objeto desejado. E, em seguida, usar ponteiros estáticos para os objetos já alocados, armazenar esses valores devolvidos (usando variáveis ??estáticas e / ou variáveis ??membro) para execução posterior dos vários objetos.

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

Por favor, seja avisado. Isto é tudo da memória porque eu não tenho escrito qualquer C ++ em mais de 8 meses.

Também Nota:. Isto tem uma séria desvantagem em que você está alocando um monte de RAM em tempo de compilação

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top