Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Объектно-ориентированный подход в С 
:(
    Опции темы
anthony
Дата 25.9.2007, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 25.6.2007
Где: Украина

Репутация: 3
Всего: 5



Задача состоит в анализе возможностей использования объектно-ориентированной методологии в С.
Remark. Проект Laurent Deniau во многом ориентирован на другой подход к решению этой проблемы, однако проведение аналогий с ним или точное указание на использованные там механизмы приветствуется.
Рассмотрим код С, который демонстрирует динамическое связывание функций.
Данный код иллюстрирует использование возможности корректной реализации полиморфизма в С без использования каких либо расширений. Полная реализация находится в прилагаемом архиве.
Извиняюсь за небрежности в написании тестовой части, однако, она создана как временный пример. В то время как описание ядра является полным и корректным.

Код

#include <stdio.h>
#include <stdlib.h>
#include "objects_targeting.h"
#include "objects_object.h"
#include "shape.h"
#include "shape_circle.h"
#include "shape_square.h"

#define OBJECTS_COUNT 2

int main ( void ) {
    Object_Ref *objects = malloc ( sizeof ( *objects ) * OBJECTS_COUNT );

    objects [ 0 ] = ( Object_Ref ) shape_circle_create ( 1 );
    objects [ 1 ] = ( Object_Ref ) shape_square_create ( 2 );

    for ( int object_index = 0; object_index < OBJECTS_COUNT; ++object_index ) {
        char *object_string = OBJECT ( objects [ object_index ] )->to_string ( );
        ( void ) printf ( "%s\n", object_string );

        objects_free ( object_string );
    }

    for ( int object_index = 0; object_index < OBJECTS_COUNT; ++object_index ) {
        OBJECT ( objects [ object_index ] )->destroy ( );
    }

    free ( objects );
    return 0;
}


Вопросы
  • Насколько обусловлено использование макросов для определения цели вызова, а не фактическая передача указателей на объекты-являющиеся целями вызова (как в gtk+).
  • Ваше общее мнение о дизайне, стиле программирования и так далее.
  • Замеченные ошибки, неточности (особенно семантические или стилистические).
  • Есть ли у кого-нибудь идеи по реализации интерфейсов. Целостность при динамическом приведении типов обеспечивается построением структуры на основе указателей, имеющих фиксированный размер и порядка их следования. Такой подход применим для одиночного наследования, однако не применим для множественного или для интерфейсов.
  • Можно ли написать макрос для быстрой реализации прокси-функции.

PS. Анализ данного кода требует некоторого знания С и объектно-ориентированной методологии (в частности, определение цели вызова и полиморфизм).

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  Objects_In_C.7z 3,13 Kb
PM MAIL ICQ   Вверх
Lazin
Дата 25.9.2007, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Прикольно конечно, но мне кажется не очень эффективно по причине того, что для доступа на уровень иерархии N, нужно использовать N косвенных обращений. 
То есть если у нас есть класс Shape_Circle производный от Shape, который в свою очередь является производным от Object, то для доступа к методам или свойствам Object получится цепочка shape_circle->super->super_->call(). 
Мне кажется можно попытаться сделать это по другому:

Код


typedef char * ( *object_to_string ) ( void );

typedef void ( *object_destroy ) ( void* );

//интерфейс "базового" класса
#define DECLARE_BASE_INTERFACE \ //vtable
      object_to_string to_str;\
      object_destroy free;\
      //data
      int type_info;\

typedef struct Base
{
 DECLARE_BASE_INTERFACE
};

#define FOO 1
typedef struct Foo
{
 DECLARE_BASE_INTERFACE
 //foo members
 int foo;
};

//виртуальный деструктор Foo
void foo_destroy ( void* this)
{
  free((Foo*)this);
}

//конструктор Foo
Base* new_foo(int data)
{
  Foo* f = malloc( sizeof(Foo) );
  f->foo = data;
  f->type_info = FOO;
  f->free = &foo_destroy();
  ****
  return f;
}

//использование
//создаём
Base* b = new_foo(9);
//вызов метода (1й параметр - this)
b->to_str(b);
//деструктор
b->free(b);

Это может работать потому что структура Foo состоит из тех - же элементов что и Base, плюс свои данные. Поэтому можно обращаться к Foo через указатель на Base. Каждому методу нужно передавать указатель на объект для которого происходит вызов.

Это сообщение отредактировал(а) Lazin - 25.9.2007, 16:44
PM MAIL Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0900 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.