Конструктор по умолчанию в C

Вам нужно преобразовать целые числа в множители. Использование as.factor () для преобразования.

library("ggplot2")

exec <- data.frame(threads = c(2,4,8,16,32,64,2,4,8,16,32,64,2,4,8,16,32,64,2,4,8,16,32,64),  msgs=c("100 msg/min","100 msg/min","100 msg/min","100 msg/min","100 msg/min","100 msg/min","400 msg/min","400 msg/min","400 msg/min","400 msg/min","400 msg/min","400 msg/min","1600 msg/min","1600 msg/min","1600 msg/min","1600 msg/min","1600 msg/min","1600 msg/min","6400 msg/min","6400 msg/min","6400 msg/min","6400 msg/min","6400 msg/min","6400 msg/min"),
        qtds=c(3778.2,6000,6000,6000,6000,6000,3756.6,7462.8,14666.2,24000,24000,24000,3762.4,7445.4,14284.4,27869.8,55877.4,93407.4,2934,5427.4,10717.6,17214.2,26222.2,37333.6))

ggplot(data=exec, aes(x=as.factor(threads), y=qtds, fill=msgs)) +
geom_bar(stat="identity", position="dodge") +
scale_fill_discrete(name = "Msgs") +
  xlab("Threads") +
  ylab("Qtds") +
  theme_bw() +
  theme(legend.position = c(0.22,0.85))

enter image description here

28
задан Jonathan Leffler 22 December 2014 в 16:54
поделиться

12 ответов

Можно создать функции инициализатора, которые берут указатель на структуру. Это было обычной практикой.

Также функции, которые создают структуру и инициализируют ее (как фабрика) - таким образом, никогда нет времени, где структура является "неинициализированной" в "клиентском" коде. Конечно - который принимает, люди следуют конвенции и используют "конструктора" / фабрика...

ужасный псевдо код без проверки ошибок на malloc или свободный

somestruct* somestruct_factory(/* per haps some initializer agrs? */)
{
  malloc some stuff
  fill in some stuff
  return pointer to malloced stuff
}


void somestruct_destructor(somestruct*)
{
  do cleanup stuff and also free pointer
  free(somestruct);
}

Кто-то, вероятно, приедет и объяснит, как некоторые ранние препроцессоры/компиляторы C++ работали, чтобы сделать это все в C.

38
ответ дан Tim 28 November 2019 в 02:22
поделиться

Используя функции, чтобы создать и избавиться от структур был уже упомянут. Но в комментарии Вы упомянули желание "конструктора по умолчанию" - я думаю, что Вы подразумеваете, что хотите инициализировать некоторых (все?) полей структуры к значениям по умолчанию.

Это сделано в C, использующем некоторую конвенцию кодирования - или функции, макросы или соединение. Я обычно делаю это что-то как следующее-

struct some_struct {
    int a;
    float b;
};
#define some_struct_DEFAULT { 0, 0.0f}
struct some_struct *some_struct_create(void) {
    struct some_struct *ptr = malloc(sizeof some_struct);
    if(!ptr)
        return ptr;

    *ptr = some_struct_DEFAULT;
    return ptr;
}
// (...)
struct some_struct on_stack = some_struct_DEFAULT;
struct some_struct *on_heap = some_struct_create();
2
ответ дан gnud 28 November 2019 в 02:22
поделиться

C++ отличается от C в этом случае в уважении, что это не имеет никаких "классов". Однако C (как много других языков) может все еще использоваться для объектно-ориентированного программирования. В этом случае Ваш конструктор может быть функцией, которая инициализирует структуру. Это совпадает с конструкторами (только другой синтаксис). Другое различие - то, что необходимо выделить объект с помощью malloc () (или некоторый вариант). В C++ Вы просто использовали бы 'новый' оператор.

, например, код C++:

class A {
  public:
    A() { a = 0; }
    int a;
};

int main() 
{
  A b;
  A *c = new A;
  return 0;
}

эквивалентный код C:

struct A {
  int a;
};

void init_A_types(struct A* t)
{
   t->a = 0;
}

int main()
{
   struct A b;
   struct A *c = malloc(sizeof(struct A));
   init_A_types(&b);
   init_A_types(c);
   return 0;
}

функция 'init_A_types' функции, поскольку конструктор был бы в C++.

21
ответ дан Reed 28 November 2019 в 02:22
поделиться

Давайте говорить о полном техническом решении, которое считали лучшей практикой в былые дни.

проблема со структурами состоит в том, что все общедоступно, таким образом, нет никакого сокрытия данных.

Мы можем зафиксировать это.

Вы создаете два заголовочных файла. Каждый - "общедоступный" заголовочный файл, используемый клиентами Вашего кода. Это содержит определения как это:

typedef struct t_ProcessStruct *t_ProcessHandle;

extern t_ProcessHandle NewProcess();
extern void DisposeProcess(t_ProcessHandle handle);

typedef struct t_PermissionsStruct *t_PermissionsHandle;

extern t_PermissionsHandle NewPermissions();
extern void DisposePermissions(t_PermissionsHandle handle);

extern void SetProcessPermissions(t_ProcessHandle proc, t_PermissionsHandle perm);

затем Вы создаете частный заголовочный файл, который содержит определения как это:

typedef void (*fDisposeFunction)(void *memoryBlock);

typedef struct {
    fDisposeFunction _dispose;
} t_DisposableStruct;

typedef struct {
    t_DisposableStruct_disposer; /* must be first */
    PID _pid;
    /* etc */
} t_ProcessStruct;

typedef struct {
    t_DisposableStruct_disposer; /* must be first */
    PERM_FLAGS _flags;
    /* etc */
} t_PermissionsStruct;

и затем в Вашей реализации можно сделать что-то вроде этого:

static void DisposeMallocBlock(void *process) { if (process) free(process); }

static void *NewMallocedDisposer(size_t size)
{
    assert(size > sizeof(t_DisposableStruct);
    t_DisposableStruct *disp = (t_DisposableStruct *)malloc(size);
    if (disp) {
       disp->_dispose = DisposeMallocBlock;
    }
    return disp;
}

static void DisposeUsingDisposer(t_DisposableStruct *ds)
{
    assert(ds);
    ds->_dispose(ds);
}

t_ProcessHandle NewProcess()
{
    t_ProcessHandle proc =  (t_ProcessHandle)NewMallocedDisposer(sizeof(t_ProcessStruct));
    if (proc) {
        proc->PID = NextPID(); /* etc */
    }
    return proc;
}

void DisposeProcess(t_ProcessHandle proc)
{
    DisposeUsingDisposer(&(proc->_disposer));
}

то, Что происходит, - то, что Вы делаете предописания для своих структур в Ваших общедоступных заголовочных файлах. Теперь Ваши структуры непрозрачны, что означает, что клиенты не могут dick с ними. Затем в полном объявлении Вы включаете деструктор в начале каждой структуры, которую можно назвать в общем. Можно использовать то же malloc средство выделения для всех, кого то же располагает функцию и так. Вы обнародовали, устанавливал/получал функции для элементов, которые Вы хотите выставленный.

Внезапно, Ваш код намного более нормален. Можно только получить структуры от средств выделения или функции, которые называют средства выделения, что означает, что Вы можете инициализация узкого места. Вы создаете в деструкторах так, чтобы объект мог быть уничтожен. И на Вас идут. Между прочим, лучшее имя, чем t_DisposableStruct могло бы быть t_vTableStruct, потому что вот что это значит. Можно теперь создать виртуальное наследование при наличии vTableStruct, который является всеми указателями функции. Можно также сделать вещи, которые Вы не можете делать на чистом oo языке (обычно), как изменяющиеся избранные элементы vtable на лету.

важный момент - то, что там технический шаблон для того, чтобы сделать структуры безопасными и initializable.

11
ответ дан plinth 28 November 2019 в 02:22
поделиться

Нет, не непосредственно. Самое близкое, которое Вы могли сделать, должно записать функцию, которая выделила экземпляр и заполнила некоторые поля.

8
ответ дан ConcernedOfTunbridgeWells 28 November 2019 в 02:22
поделиться

Можно записать функцию, которая возвращает структуру C:

struct file create_file(int i, float f) {
    struct file obj = { i, f };
    // other code here...
    return obj;
}

, Если Вы задаетесь вопросом, могут ли у Вас быть "нормальные" функции членства в C. Ну, Вы можете в некоторой степени. Я предпочитаю стиль object-as-first-argument. Вы передаете указатель на свою структуру как первый аргумент. Таким образом, у Вас может быть несколько функций, определяя интерфейс к Вашим объектам:

int file_get_integer(struct file *self) { return self->i; }
float file_get_float(struct file *self) { return self->f; }

, Если Вы пишете в том стиле, что Вы имеете в конце, абстрактный тип данных. Я видел, что парни эмулируют синтаксис вызова функции членства, используемый в C++ при наличии указателей функции в их структуру и затем выполнение:

obj.get_integer(&obj);

Это используется ядром Linux для определения интерфейса к драйверам файловой системы. Это - стиль записи, что можно любить или не может любить. Мне не нравится он слишком много, потому что я продолжаю использовать членов структур для данных, а не для эмуляции функций членства звонит для сходства с на популярных объектно-ориентированных языках.

4
ответ дан Johannes Schaub - litb 28 November 2019 в 02:22
поделиться

Предположение, что Вы хотите сделать это в C, таким образом, Ваш вопрос не о структурах в C++:

то, Что я обычно делаю, - то, что я просто создаю функцию, init_whatever, который берет указатель на структуру (или другая переменная) и устанавливает ее на значения, которые я хочу.

, Если это - глобальная переменная (который инициализируется для обнуления) Вы могли , вид моделирует конструктора аргумента меньше при наличии "инициализированного" флага в нем и затем позволил Вашим другим функциям проверить, что флаг, и инициализирует структуру, если флаг является нулем. Я нисколько не уверен, что это - хорошая идея, все же.

И, поскольку кто-то еще отметил, Вы могли также сделать что-то ужасное с макросами...

2
ответ дан Thomas Padron-McCarthy 28 November 2019 в 02:22
поделиться

В основном C++ создает списки указателей, которые содержат адреса методов. Этот список называют определением класса (в определении класса существуют еще некоторые данные, но мы игнорируем это на данный момент).

А общий шаблон, чтобы иметь "классы" в чистом C должен определить "класс структуры". Одно из полей структуры является функцией фабрики, которая возвращает "экземпляры" класса. Я предлагаю использовать макрос для сокрытия бросков:

typedef struct __class * class;
typedef void (*ctor_ptr)(class);
struct class {
    char * name;
    ctor_ptr ctor;
    ... destructor and other stuff ...
}

#define NEW(clz) ((struct something *)(((struct class *)clz)->ctor(clz)))

Теперь, можно определить классы, которые Вы имеете путем создания структур типа "класс структуры" для каждого класса, Вы имеете и затем называете конструктора сохраненным в них. То же идет для деструктора, и т.д.

, Если Вы хотите методы для своих экземпляров, должны поместить их в структуры класса и сохранить указатель на класс в структуре экземпляра:

#define NEW_SOMETHING() ((struct something *)NEW(&something_definition))
#define METHOD(inst, arg) ((struct something_class *)(((struct something *)inst)->clz)->method(inst, arg))

NEW_SOMETHING создаст новый экземпляр "чего-то" с помощью определения класса, сохраненного в структуре something_definition. МЕТОД вызовет "метод" на этот экземпляр. Обратите внимание, что для реального кода, Вы захотите проверить, что inst на самом деле экземпляр something (сравните указатели класса, что-то как этот).

, Чтобы иметь наследование немного хитро и лев как осуществление для читателя.

Примечание, что можно сделать все, которое можно сделать в C++ в чистом C. Компилятор C++ волшебно не заменяет Ваш ЦП чем-то еще. Просто требуется намного больше кода, чтобы сделать это.

, Если Вы хотите посмотреть на пример, проверьте бойкий (часть Gtk + проект).

3
ответ дан Aaron Digulla 28 November 2019 в 02:22
поделиться

Едва ли. Если я помню правильно, самыми близкими, которые Вы получаете к классам, являются структуры. Вы выделяете память и заполняете поля. Я не вижу, как Вы сделали бы вещь типа общего конструктора для этого. Теоретически, Вы могли записать макрос, который сделает часть этого. Не уверенный, если это действительно стоит все же.

1
ответ дан paul 28 November 2019 в 02:22
поделиться

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

, Если это не работает на Вас затем, смотрят на GObject. http://en.wikipedia.org/wiki/GObject . Это - объектная система для C, используемого в GTK и Gnome, который в значительной степени проворачивает "объекты в C" к 11.

Из Википедии:

Бойкая Объектная Система или GObject, является библиотекой бесплатного программного обеспечения (покрытый LGPL), который обеспечивает портативную объектную систему и прозрачное межъязыковое взаимодействие.

система поддерживает конструкторов, деструкторы, единичное наследование, интерфейсы, виртуальные открытые и закрытые методы и т.д. Это также намного более утомительно и трудно, чем выполнение того же самого в C++.развлекайтесь!

1
ответ дан joeforker 28 November 2019 в 02:22
поделиться

Нет, структуры являются только набором данных. Вы не можете объявить функции в структурах, таким образом, нет никакого способа создать конструктора для него.

0
ответ дан soulmerge 28 November 2019 в 02:22
поделиться

Вот немного макро-волшебства вокруг malloc(), memcpy() и C99 соединяют литералы:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define new(TYPE, ...) memdup(&(TYPE){ __VA_ARGS__ }, sizeof(TYPE))

void * memdup(const void * obj, size_t size)
{
    void * copy = malloc(size);
    return copy ? memcpy(copy, obj, size) : NULL;
}

struct point
{
    int x;
    int y;
};

int main()
{
    int * i = new(int, 1);
    struct point * p = new(struct point, 2, 3);

    printf("%i %i %i", *i, p->x, p->y);

    return 0;
}
2
ответ дан Christoph 28 November 2019 в 02:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: