开发者

Initializing a class using malloc

I am working on a toy language for avr using C++ as the intermediate language, Problem is avr-gcc does not have new implemented. All my object derive from the class Object which has virtual methods when I create say a float object with malloc using instructions from,

Can I implement the Factory Method pattern in C++ without using new?

as soon a开发者_运维技巧s I cast it to an Object to pass around and back to a Float my program crashes, comments in the answer says that this is due to vtable not initializing properly, so how can i create a c++ object without using new and have the vtable setup properly?


It appears that new as a language construct is supported, but the operator new code that underlies it and does the actual allocation isn't implemented.

It should be pretty easy to fix that by providing your own implementation for operator new in your source code:

In some header file that's included in any file needing new

#include <stdlib.h> 

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

In a single cpp file.

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

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

Source: this post on avrfreaks.net, which also contains information about some other stuff you may want/need to implement on your own.


It depends on the hardware platform you are compiling to, but the layout is usually pretty similar across implementations. After all, the first C++ was CFRONT, which compiled C++ to C...

The platform-dependent issues and the memory layouts will be described in a "platform C++ ABI" where ABI stands for "Application Binary Interface."

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

Here is a possible constructor, which actually makes two different kinds of "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;
}

Voila - polymorphism via ?:

Anyway, enjoy the language experimentation and good luck improving on C++. By basing your efforts on C, you would be off to a solid start. ;)


You can use malloc followed by placement-new which will create the object properly, constructing it at the location you specify.

Of course that still means using the keyword "new" but if what you really want to do is handle the memory / heap management and not put a total ban on that keyword then it might achieve what you are trying.


If you want to tailor the implementation to one specific version of a specific compiler, then yes, for GCC simply look into the implementation of new in the GCC code.

Otherwise no. What you can do is two-factor initialization. First allocate the memory (malloc() or operator new()) and then initialize using placement new.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜