Инициализация класса с использованием malloc - PullRequest
2 голосов
/ 10 апреля 2011

Я работаю над игрушечным языком для avr, используя C ++ в качестве промежуточного языка. Проблема в том, что в avr-gcc не реализовано новое.Весь мой объект происходит от класса Object, который имеет виртуальные методы, когда я создаю, скажем, объект с плавающей точкой с помощью malloc, используя инструкции из

Могу ли я реализовать шаблон метода фабрики в C ++ без использования new?

как только я приведу его к объекту для передачи и обратно во Float, моя программа аварийно завершится, комментарии в ответе говорят, что это происходит из-за неправильной инициализации vtable, так как я могу создать объект c ++без использования нового и правильной настройки vtable?

Ответы [ 4 ]

5 голосов
/ 10 апреля 2011

Похоже, что new как языковая конструкция поддерживается, но код operator new, который лежит в основе этого и выполняет фактическое распределение, не реализован.

Это легко исправить, предоставив собственную реализацию operator new в исходном коде:

В некоторых заголовочных файлах, которые включены в любой файл, требующий new

#include <stdlib.h> 

void * operator new(size_t size); 
void operator delete(void * ptr);

В одном файле cpp.

void * operator new(size_t size) 
{ 
  return malloc(size); 
} 

void operator delete(void * ptr) 
{ 
  free(ptr); 
} 

Источник: этот пост на avrfreaks.net, который также содержит информацию о некоторых других вещах, которые вы можете / должны реализовать самостоятельно.

3 голосов
/ 10 апреля 2011

Это зависит от аппаратной платформы, на которую вы компилируете, но в разных реализациях компоновка обычно очень похожа.В конце концов, первым C ++ был CFRONT, который скомпилировал C ++ в C ...

Проблемы, зависящие от платформы и схемы памяти, будут описаны в «ABI платформы C ++», где ABI означает «двоичный интерфейс приложения».. "

struct Cxx_ABI_Header
{
    unsigned inheritance_backward_offset;  /* Must be Zero for base object */
    unsigned rtti; /* Each class has its own signature. */
    void * vtable; /* Pointer to array of virtual function pointers. */
}

struct object_one
{
     char * file_name;
     int file_descriptor;
}

int object_one_create_file(struct object_one *);
int object_one_delete_file(struct object_one *);
int object_one_update_file(struct object_one *, off_t offset, 
                           size_t nbytes_replace, size_t nbytes_supplied,
                           char * buf);
int object_one_read_file(struct object_one *, off_t offset, 
                         size_t nbytes_read, char * buf);
int object_one_op_noauthz(struct object_one *)
{
    return ENOACCESS;
}

void * CRUD_vtable_authenticated_user = {
    { object_one_create_file, object_one_read_file,
      object_one_update_file, object_one_delete_file }};

void * CRUD_vtable_guest = {
    { object_one_op_noauthz, object_one_read_file,
      object_one_op_noauthz, object_one_op_noauthz }};

Вот возможный конструктор, который на самом деле создает два разных типа" object_one ".

struct object_one * new_object_one(char * filespec, int user_id)
{
    size_t n_bytes = sizeof(struct Cxx_ABI_Header) + sizeof(struct object_one);
    void * pheap = malloc(n_bytes);
    struct * pCxx_ABI_Header pcxx = pheap;
    struct * pObject  pobj = (void *)((char *)pheap 
                                               + sizeof(struct Cxx_ABI_Header));

    if (!pheap) ...

    pcxx->inheritance_backward_offset = 0;
    pcxx->rtti = /* You tell me? */
    pcxx->vtable = (userid < 0 ) ? CRUD_vtable_guest 
                                 : CRUD_vtable_authenticated_user;

    pobj->file_name = strdup(filespec);
    pobj->file_descriptor = 0;

    return pobj;
}

Вуаля - полиморфизм через ?:

В любом случае, наслаждайтесь языковыми экспериментами и удачи в улучшении C ++.Основывая свои усилия на C, вы начнете с самого начала.;)

1 голос
/ 10 апреля 2011

Вы можете использовать malloc с последующим размещением-новым, чтобы правильно создать объект, создав его в указанном вами месте.

Конечно, это по-прежнему означает использование ключевого слова "new", но если вы действительно хотите управлять памятью / кучей и не устанавливать полный запрет для этого ключевого слова, то это может привести к тому, что вы пытаетесь.

0 голосов
/ 10 апреля 2011

Если вы хотите адаптировать реализацию к одной конкретной версии определенного компилятора, то да, для GCC просто посмотрите на реализацию new в коде GCC.

В противном случае нет.Что вы можете сделать, это двухфакторная инициализация.Сначала выделите память (malloc() или operator new()), а затем инициализируйте, используя новое размещение.

...