The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



"Программирование объектов на Си в стиле Go"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (C/C++)
Изначальное сообщение [ Отслеживать ]

"Программирование объектов на Си в стиле Go"  +/
Сообщение от zionist (ok), 03-Янв-26, 03:04 
Как вам такая демонстрация идеи программиования объектов на Си в стиле Go?

Тут поддерживается скрытие приватных полей и композиция методов.

goc.h

#ifndef GOC_H
#define GOC_H

#define fn(obj, fn, ...) (obj).fn(&(obj), ##__VA_ARGS__)

#endif

woman.h

#ifndef WOMAN_H
#define WOMAN_H

#include "goc.h"

struct woman;

typedef struct w {
    struct woman *w;
    void (* hug)(struct w *self);
    void (* kiss)(struct w *self);
} woman;

woman new_woman(char *);
void free_woman(woman *);

#endif

woman.c

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

#include "woman.h"

struct woman {
    char *name;
    bool hugged;
    bool kissed;
};

void hug(woman *self) {
    if (self->w == NULL) {
        printf("No woman allocated!\n");
        return;
    }

    printf("You're hugging %s\n", self->w->name);

    if (self->w->hugged) {
        printf("%s say: It hurts, get off me!\n", self->w->name);
        return;
    }
    if (self->w->kissed) {
        printf("%s say: Get off me, butch!\n", self->w->name);
        return;
    }

    self->w->hugged = true;
    printf("%s say: you're sweet!\n", self->w->name);
}

void kiss(woman *self) {
    if (self->w == NULL) {
        printf("No woman allocated!\n");
        return;
    }

    printf("You're kissing %s\n", self->w->name);

    if (!self->w->hugged) {
        if (self->w->kissed) {
            printf("%s is calling the police!\n", self->w->name);
            return;
        }
        self->w->kissed = true;
        printf("%s say: How dare you?\n", self->w->name);
        return;
    }
    if (self->w->kissed) {
        printf("%s say: Level up, boy!\n", self->w->name);
        return;
    }

    self->w->kissed = true;
    printf("%s say: Mwah!\n", self->w->name);
}

woman new_woman(char *name) {
    struct woman *w = calloc(1, sizeof(struct woman));
    w->name = name;
    woman women = {
        .w = w,
        .hug = hug,
        .kiss = kiss
    };
    return women;
}

void free_woman(woman *w) {
    free(w->w);
    w->w = NULL;
}

main.c

#include <stdio.h>

#include "woman.h"

int main(void)
{
    woman woman;

    printf("\033[1mThe right workflow:\033[0m\n");

    woman = new_woman("Alice");
    fn(woman, hug);
    fn(woman, kiss);
    fn(woman, kiss);
    free_woman(&woman);

    putchar('\n');

    printf("\033[1mThe wrong workflow:\033[0m\n");

    woman = new_woman("Miranda");
    fn(woman, kiss);
    fn(woman, hug);
    fn(woman, kiss);
    free_woman(&woman);

    putchar('\n');

    printf("\033[1mThe dreaming workflow:\033[0m\n");

    fn(woman, hug);
    fn(woman, kiss);
    fn(woman, kiss);

    return 0;
}

Программа печатает:

The right workflow:
You're hugging Alice
Alice say: you're sweet!
You're kissing Alice
Alice say: Mwah!
You're kissing Alice
Alice say: Level up, boy!

The wrong workflow:
You're kissing Miranda
Miranda say: How dare you?
You're hugging Miranda
Miranda say: Get off me, butch!
You're kissing Miranda
Miranda is calling the police!

The dreaming workflow:
No woman allocated!
No woman allocated!
No woman allocated!


Ответить | Правка | Cообщить модератору

Оглавление

Сообщения [Сортировка по времени | RSS]


1. "Программирование объектов на Си в стиле Go"  +/
Сообщение от й (?), 04-Янв-26, 14:36 
RAII лучше реализуй. Автоматическое или полуавтоматическое. Оно полезнее будет.
Ответить | Правка | Наверх | Cообщить модератору

2. "Программирование объектов на Си в стиле Go"  +/
Сообщение от Аноним (2), 04-Янв-26, 19:27 
typedef woman и struct woman - лучше чтоб различались по имени.

Композиции методов я не увидел, только инсталляцию методов.

Сокрытие закрытых полей ... Тут есть доступ к полю w, и через него можно повредить данные в w.

Think different - это не проблема, но лучше так не делать. Для программирования объектов на С лучше применяйте традиционный способ - модульное программирование, как в Modula-2.

Ответить | Правка | Наверх | Cообщить модератору

3. "Программирование объектов на Си в стиле Go"  +/
Сообщение от zionist (ok), 05-Янв-26, 00:42 
> typedef woman и struct woman - лучше чтоб различались по имени.

Они всё равно в разных пространствах имён и перепутать их трудно.

> Композиции методов я не увидел, только инсталляцию методов.

В чём разница?

> Сокрытие закрытых полей ... Тут есть доступ к полю w, и через
> него можно повредить данные в w.

Только через грязные хаки с адресной арифметикой. Нормального доступа к его полям нет.

> Think different - это не проблема, но лучше так не делать. Для
> программирования объектов на С лучше применяйте традиционный способ - модульное программирование,
> как в Modula-2.

Каким образом? Основная мотивация прикрепить функцию к объекту - перенести её из глобального пространства имён в пространство имён конкретной функции. При этом в Си, к сожалению, нет механизма автоматической передачи ссылки или копии объекта через первый аргумент функции (в Go это называется ресивер). Именно поэтому пришлось городить макрос fn.

Ответить | Правка | Наверх | Cообщить модератору

4. "Программирование объектов на Си в стиле Go"  +/
Сообщение от arvenia (ok), 05-Янв-26, 14:52 
Идея понятна и макрос fn выглядит аккуратно, но цена — лишняя сложность и риск поломать инварианты. Для C модульный подход всё же читается и сопровождается проще😊


Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2026 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру