LINUX.ORG.RU

Как добавлять переменные-члены (member variables)?

 ,


0

1

Там есть два макроса:
G_DECLARE_FINAL_TYPE
G_DECLARE_DERIVABLE_TYPE

Если использовать первый, то там зафиксирован тип(класс):
typedef struct { ParentName##Class parent_class; } ModuleObjName##Class; \
и поэтому в него не получится дописывать виртуальные функции.

А если использвоать второй, то там зафиксирован объект:
struct _##ModuleObjName { ParentName parent_instance; };
и поэтому в него не получится дописывать переменные-члены.

Можно, конечно, сделать два класса: первый с функциями, второй - наследник от первого с перменными-членами. Но это, на мой взгляд, избыточно.

Вопрос: что нужно писать вместо макросов, G_DECLARE_FINAL_TYPE и G_DECLARE_DERIVABLE_TYPE, чтобы можно было добавлять и виртуальные функции и переменные-члены?

Тебе нужен derivable-type, а описывай его с помощью G_DEFINE_TYPE_WITH_PRIVATE. Опиши ещё одну структуру вида _MyObjectPrivate с приватными полями, которая будет доступна через функцию вида my_object_get_instance_private(MyObject* self). Инкапсуляция, ничего не попишешь.

https://habr.com/post/418443/

meliafaro ★★★★★ ()
Последнее исправление: meliafaro (всего исправлений: 1)
Ответ на: комментарий от meliafaro

Но ведь если тип у меня FINAL, то там есть описание структуры и туда можно напихать (публичных?) полей. Им удобно присваивать всякие значения в коде. Что же мне их теперь в private тоже переделывать?

Это как-нибудь связано с introspection?

UPD: прочитал статью, она не отвечает на этот вопрос. Ведь если можно для FINAL запихнуть в струтуру объекта, то это значит что и в принципе так можно делать для DERIVABLE

Einstok_Fair ★★☆ ()
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от meliafaro

Можно ещё было бы сказать, что DERIVABLE не может содержать данных, для того, чтобы таблица функций этими данными не разбивалась на части, но какая разница, если и будут разбиваться?

Куда помещается указатель на private data?
не нашел документацию на g_type_add_instance_private

Einstok_Fair ★★☆ ()
Последнее исправление: Einstok_Fair (всего исправлений: 2)
Ответ на: комментарий от Einstok_Fair

Описание структуры для final-типа обычно выносится в .c-файл, файл с реализацией, соответственно, поля будут недоступны для непосредственного изменения в коде. Создавай обычную структуру или наследуйся от GObject, но доступ к полям будет только через геттеры/сеттеры или свойства.

Можешь в заголовочнике вручную всю лапшу расписать:

#define MY_TYPE_OBJECT             (my_object_get_type ())
#define MY_OBJECT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_OBJECT, MyObject))
#define MY_OBJECT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_OBJECT, MyObjectClass))
#define MY_IS_OBJECT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_OBJECT))
#define MY_IS_OBJECT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_OBJECT))
#define MY_OBJECT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_OBJECT, MyObjectClass))

typedef struct MyObject_         MyObject;
typedef struct MyObjectClass_    MyObjectClass;
typedef struct MyObjectPrivate_  MyObjectPrivate;

struct MyObject_
{
  GObject parent;
  /* add your public declarations here */
  MyObjectPrivate *priv;
};

struct MyObjectClass_
{
  GObjectClass parent_class;
};


GType my_object_get_type (void);
meliafaro ★★★★★ ()
Ответ на: комментарий от meliafaro

я думаю что так:
MyObjectPrivate *priv;
библиотека GLib не делает.

When an object is allocated, the private structures for the type and all of its parent types are allocated sequentially in the same memory block as the public structures, and are zero-filled.

тут упоминаются «все типы», в общем как-то всё беспримерно.

Einstok_Fair ★★☆ ()
Ответ на: комментарий от Einstok_Fair

я думаю что так:

MyObjectPrivate *priv; библиотека GLib не делает.

Возможно, сейчас не могу проверить. В ранних версиях GLib всё это расписывали руками, сейчас для упрощения появились макросы вроде G_DECLARE_FINAL_TYPE для самых распространённых случаев.

meliafaro ★★★★★ ()
Ответ на: комментарий от meliafaro

мне не ясны две части английской фразы:
1) что значит «в том же самом блоке», получается что при выделении памяти под структуру нужно увеличивать её размер
2) что значит «для всех родителей». Входят ли в список «всех» данные последнего (FINAL) класса. Если я напишу его с макросом G_DEFINE_TYPE_WITH_PRIVATE.

Надо ли в конструкторе потомка вызывать конструктор родителя?

Einstok_Fair ★★☆ ()
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от Einstok_Fair

Думаю, это просто означает, что тебе нет нужды вручную выделять память самостоятельно под объект и все связанные структуры, память под них выделяется библиотекой.

meliafaro ★★★★★ ()
Ответ на: комментарий от Einstok_Fair

Надо ли в конструкторе потомка вызывать конструктор родителя?

Что имеется в виду под конструктором? Если функция вроде my_type_init, то нет. Если ты переопределяешь constructor или constructed из GObjectClass, то ты что-то делаешь неправильно да, как и в случае с деструкторами.

meliafaro ★★★★★ ()
Ответ на: комментарий от meliafaro

я имею в виду - как переписать код

static void
om1_mother_init(Om1Mother* self)
{
    printf("Mother was born.\n");
    self->current_frame = NULL;
}

в случае если мама наследуется от какой-то базы

Einstok_Fair ★★☆ ()
Ответ на: комментарий от anonymous

Это если вручную писать. Я использовал плагин генератора классов для Geany. Ну и в GLib уже давно есть макросы, сильно сокращающие эту писанину.

meliafaro ★★★★★ ()
Ответ на: комментарий от meliafaro

C двумя целями:
1) чтобы использовать private data вместо данных в структуре _Om1Mother
2) чтобы инициализировать данные базового класса.

Вомзожно, что в аналогичной функции базового класса создаётся массив, как-то так:

    self->frames = g_ptr_array_sized_new(1000);
    g_ptr_array_set_free_func(self->frames, om1_motherbase_onframeremoved);

Если функция инициализации не будет вызвана, то переменная базового класса будет указывать не на массив, а на адрес 0.

Einstok_Fair ★★☆ ()
Ответ на: комментарий от meliafaro

Сделал все данные приватными.

Перестала работать диагностика в main.c:

    printf("frame 'clean' flag is %s\n", frame->clean?"true":"false");

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

Einstok_Fair ★★☆ ()
Ответ на: комментарий от Einstok_Fair
static void
om1_mother_init(Om1Mother* self)
{
    Om1MotherPrivate* priv = om1_mother_get_instance_private(self);
    /* инициализируешь приватные данные */
    self = (ParentType*) self;
    /* работаешь с данными родительского типа */
}

Только кастовать лучше через макросы вида OM1_MATHER().

meliafaro ★★★★★ ()
Ответ на: комментарий от Einstok_Fair

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

Ну так в С++ и Жабе так же, по крайней мере, на практике.

meliafaro ★★★★★ ()
Последнее исправление: meliafaro (всего исправлений: 1)
Ответ на: комментарий от kirk_johnson

Нужно срочно сообщить в соответствующие структуры. Они то с этим сексистом быстро разберутся. Найдут несколько изнасилованных девушек/парней и все.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.