LINUX.ORG.RU

[рукииз...] Как разрешить циклические зависимости?


0

0

Есть у меня 2 заголовочных файла: gtk.h и spots.h. В первом определена структура _Window, одним из членов которой является структура _Spots, определенная во втором. А во втором есть функция с аргументом struct _Window*.

Вопрос: как мне избавиться от циклической зависимости этих структур?

☆☆☆☆☆
Ответ на: комментарий от Absurd

Не помогает. Как можно сделать forward declaration для структуры? А incomplete type тоже непонятно чем спасет.

Компилятор выдает такую ошибку:

ошибка: декларация 'struct _Window' внутри списка параметров

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от arsi

Спасибо! Я сначала extern перед struct _Window писал - компилятор матюкался. А так работает!..

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от arsi

В общем, если мне не хочется в каждом заголовочном файле дополнительно писать struct _Window, struct _Spots и т.п., то можно создать отдельный .h-файл, куда только это и записать, а его уже подключать в те файлы, где нужно разрешить циклическую зависимость?

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em
struct _Window 

обращаю Ваше внимание на то что имена переменных начинающиеся с подчёркивания за которым идёт прописная буква зарезервированы для внутренних нужд, и, как минимум, их надо оборачивать в namespace, но лучше вообще не использовать

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

В общем, если мне не хочется в каждом заголовочном файле дополнительно писать struct _Window, struct _Spots и т.п., то можно создать отдельный .h-файл, куда только это и записать, а его уже подключать в те файлы, где нужно разрешить циклическую зависимость?

я обычно, увидев зачатки вот таких вот циклических зависимостей у себя в коде, начинаю подозревать bad design, ИЧСХ часто оказываюсь прав :)

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

Просто само имя Window у меня определяется как

typedef struct _Window Window;
И так же с остальными структурами (чтобы в дальшейшем не писать каждый раз struct ... ).

Знаю, что это зло, но пока не нарывался, наступаю иногда на грабли...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от shty

Ну, я просто разнес функции, выполняющие разный функционал, в разные файлы. Файл gtk.c у меня и так уже за 1100 строк зашкалил - надо будет его тоже разбивать...

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

>А так работает!..

Это и есть forward declaration. Теперь надо изучить что такое incomplete type.

В общем, если мне не хочется в каждом заголовочном файле дополнительно писать struct _Window, struct _Spots и т.п., то можно создать отдельный .h-файл, куда только это и записать, а его уже подключать в те файлы, где нужно разрешить циклическую зависимость?

Использование #include в контексте .h файла надо минимизировать. Правда, это в первую очередь относится к С++.

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

это ты уже спроси совета у своего чувства прекрасного ;) но если тебе так часто приходится решать циклические зависимости, может проще навести порядок в хэдерах?

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

Это и есть forward declaration. Теперь надо изучить что такое incomplete type.

Честно говоря, чем там может спасти неполный тип, не представляю...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от arsi

Боюсь, на разгребание этих авгиевых конюшен уйдет очень много времени.

Да и не хочется лепить в один файл разнородные по смыслу функции.

Кроме того, не хочется слишком большие файлы лепить - ориентироваться в них очень тяжело (у меня и так перечень функций gtk.h в geany два экрана по вертикали занимает :) ).

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от arsi

Про такой вариант я и не подумал :)

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

ну сделайте

typedef struct { /* ... */ } Window;

или как-то по другому назовите, типа не _Window a window_struct, или, раз уж подчёркивание глянулось _window_struct, или ещё как (согласно Вашему code style)

и используйте первое подчёркивание только внутри своего namespace, иначе тоже можно налететь

суть в том, что названия начинающиеся с подчёркивания и большой буквы часто используются в потрохах всяческих библиотек и пр. налетите на уличную магию, потеряете ведь несколько дней просто так, тем более что Window это такое слово, у которого частота встречаемости довольно таки высокая

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

> Честно говоря, чем там может спасти неполный тип, не представляю...

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

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

используйте первое подчёркивание только внутри своего namespace

У меня не «плюсы», а C.

А сделать

 typedef struct { /* ... */ } Window;
я не могу, т.к. внутри структуры Window есть еще ссылочка на родительское окно.

суть в том, что названия начинающиеся с подчёркивания и большой буквы часто используются в потрохах всяческих библиотек и пр. налетите на уличную магию, потеряете ведь несколько дней просто так, тем более что Window это такое слово, у которого частота встречаемости довольно таки высокая

Спасибо, буду иметь в виду. Сейчас, пока не накопилось слишком много кода, поисправляю «косяки».

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

Боюсь, на разгребание этих авгиевых конюшен уйдет очень много времени.

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

Да и не хочется лепить в один файл разнородные по смыслу функции.

Кроме того, не хочется слишком большие файлы лепить [..]

то, что Вы упомянули ни в коем случае не разгребание, это называется поддать огоньку

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

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

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от arsi

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

не «можно», а только так и «нужно»

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

> Так там же перекрестные ссылки.

вот именно их я и предлагаю решить, отделив мух от котлет:

gtk.h:

typedef Window Window;

spots.h:

#include "gtk.h"
typedef Spots Spots;
int foo(Window *, Spots *);

gtk_p.h (приватный):

#include "gtk.h"
#include "spots.h"

struct Window {
	...
	Spots *spots;
	...
};

spots.c:

#include "gtk_p.h"
#include "spots.h"

struct Spots {
	...
};

int foo(Window *win, Spots *sp) {
	...
}

как-то так.

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