Подтвердить что ты не робот

Борьба с C от объектно-ориентированной земли?

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

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

Может ли опытный программист C объяснить, как я должен думать о своих программах во время разработки?

Например, я хочу написать собственный класс Семафор. Естественно, мне нужна структура данных очереди для моей программы, которую я тоже хотел бы написать. Если бы мне нужно было сделать это на Java или С#, я бы просто взломал быстрый класс Queue и создал новый экземпляр этого класса в моем классе Semaphore.

Но в C нет объектов. Итак, нужно ли мне встраивать все поведение моей структуры данных очереди?

Может кто-нибудь помочь мне "получить это"?

Связанный: что является лучшим способом планирования и организации разработки приложения в c

4b9b3361

Ответ 1

Но в C нет объектов. Ну действуй Я должен установить все поведение моя структура данных очереди?

Нет.

Сделайте это.

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

  • Напишите атрибуты вашего класса как структуры языка C.

  • Поместите эту структуру в файл заголовка вместе со всеми функциями, которые работают с этой структурой. Убедитесь, что MyStruct * self является первым аргументом для всех этих "функций метода".

  • Напишите модуль C со всеми телами функций метода.

Плохое ОО в C. Оно работает хорошо. Просто будьте дисциплинированы в том, чтобы поместить все в структуру, которая вам нужна - переменные public и private instance - все.

Как правило, избегайте попыток иметь частные переменные. У вас нет полной возможности компилятора OO, поэтому не беспокойтесь о низкоценных функциях, таких как "private" или "protected".

Ответ 2

Я хотел бы изменить ответ С. Лотта на использование непрозрачного указателя для выполнения скрытия данных членов структуры:

  • Определите свой класс, но вы хотите использовать обычный дизайн OO.
  • Членные переменные вашего класса переходят в структуру языка C.
  • В заголовочном файле вы не хотите выставлять переменные-члены вашего объекта (поскольку они были бы "private" на языке OO). Вместо этого используйте непрозрачный указатель, т.е.
    typedef struct mystruct_s *mystruct_t; // first argument to all your methods
  • Для всех методов, которые вы хотите быть "общедоступными", поместите свои подписи в ваш .h файл. Органы методов должны войти в файл .c, а методы "private" должны быть определены только в файле .c, а также объявлены как static, чтобы их символы не сталкивались с символами, определенными в других файлах.

Умные соглашения об именах, такие как подчеркивания, не нужны с помощью этого метода, но это означает, что все ваши переменные-члены будут закрытыми. Функции могут быть общедоступными или частными, хотя публичные функции они являются частью глобального пространства имен, поэтому вы можете захотеть присвоить их имена с именем "package", таким как mystruct_push(), mystruct_pop() и т.д.

Вам также необходимо очистить, если вызывающий или библиотека отвечает за вызов malloc() и free(). Скорее всего, у вас будут методы mystruct_t *create() и void destroy(mystruct_t *target).

Ответ 3

Вы все еще можете рассматривать объект, ориентированный на C.

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

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

Существует большой pdf объектно-ориентированного программирования с ANSI-C здесь.

Ответ 4

У меня был медведь времени, переходя от процессуального к мышлению ОО, поэтому я чувствую вашу боль.

Я обнаружил, что для того, чтобы научиться создавать объекты, лучше подумать о том, как они будут смотреть на вызывающего. Тот же подход может помочь вам, идя в другую сторону. Посмотрите, как выглядит API для вашего компонента. Одним из хороших способов является изучение существующих C API (я использовал стандартные Java API как набор примеров OO API).

Вы используете компонент очереди примерно так:

import some.package.Queue;

Queue q = new Queue(); 
q.add(item);

В типичном C api вы ожидаете нечто большее:

#include <queue.h> // provides queue, make_queue(), queue_add(), others

queue q = make_queue(); // queue is probably a struct, or a struct*
queue_add(q,item);

Всякий раз, когда вы оказываетесь в объектах, делайте аналогичное преобразование.

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

Удачи!

Ответ 5

Просмотрите Lua C api. Это был мой путеводный свет до дизайна интерфейса C. Каждая функция принимает состояние Lua как ведущий аргумент, который становится вашим "this". Наследование немного сложнее, но Chipmunk удается выполнить довольно хорошую работу, выставляя функции, которые берут общие структуры форм и разрабатывают детали эта функция фактически вызывается через "класс". Вы часто можете использовать void *, чтобы функции выполняли разные типы (структуры) так, как вы перегружались в OO. Иногда он может чувствовать себя немного хакерским, но хорошо работает.

Ответ 6

Первоначально С++ был просто компилятором, который написал код C из источников С++; Затем они были скомпилированы с помощью встроенного компилятора C, связанного и т.д.

Следовательно, все методы ООП доступны в C - это просто то, что компилятор вам не поможет, и не предоставляет всех возможностей времени компиляции, таких как шаблоны, переопределения операторов, скрытие данных и т.д.

  • С++ "struct" была (вероятно, до сих пор) эквивалентна "классу" со всеми членами "public".
  • Функции-члены могут быть реализованы как указатели функций в структуре; это может обеспечить инкапсуляцию и полиморфизм. Конструкторы существуют в глобальной области, если вы не используете фабрики. Деструкторы могут быть функциями-членами.
  • Используя функции-члены доступа, такие как getColor(), setColor() может облегчить внутренние различия и обеспечить скрытие данных. Если вы действительно хотите, вы можете использовать предложение Брайана Бонди о скрытии макросов.
  • На самом деле существует много библиотек FOSS, которые предоставляют стандартные контейнеры - хэш-таблицы, динамические массивы, связанные списки и т.д.

Ответ 7

Во-вторых, предложения о том, чтобы сделать "Бедный человек OO в C." Я также думаю, что вам может понадобиться время, чтобы посмотреть, как работает Perl OO. В основном OO выполняется в Perl, когда интерпретатор предоставляет каждому методу экземпляр как неявный первый параметр. Вы захотите сделать то же самое в C, явным образом, и используйте действительно хорошую организацию кода, так как компилятор не обеспечит для вас хорошую инкапсуляцию.

Кстати, вы можете принудительно удерживать членов ваших структур с помощью непрозрачных указателей. Я, кажется, помню, что стандарты и рекомендации по программированию GNU включали в себя технику для этого, в основном отбрасывая все на void *, когда он был передан, а затем используя typedefs для обозначения каждого определенного типа непрозрачного указателя, который должен был быть передан. (то есть каждый "класс" )