Поддержу VladD2 и AndreyFedotov (для ПК)
От: Аноним  
Дата: 08.11.04 22:42
Оценка: -7
Позволил себе вынести эту ветку
Автор: Павел Кузнецов
Дата: 07.11.04
сюда т.к. не могу писать в том форуме но хотелось бы поддержать этих товарищей. Заранее приношу извинения если что не так.

ПК>Средства для обеспечения инкапсуляции есть и в C. При этом получающаяся инкапсуляция ничуть не "меньше", чем в C++.

Средства для обеспечения инкапсуляции есть и в Си, но они намного примитивнее чем в С++, о чем и говорил VladD2. См. выделенный вопрос ниже чтобы понять почему "меньше."

ПК>Ты привел неэквивалентный с точки зрения инкапсуляции пример на C. Но это не означает, что нельзя написать эквивалентный в этом отношении пример на C. Вот он:

Влад, как раз-таки, привел правильный пример, корректно демонстрирующий почему инкапсуляция в Си примитивнее, а вот Вы нет. Опять-таки, смотрите выделенный вопрос ниже.

И думаете такое (ваш пример) нельзя сделать на С++?

ПК>Заголовочный файл:

ПК>
ПК>typedef int ErrorCode;

ПК>#define A_OK                 ((ErrorCode)0)

ПК>// Требования инкапсуляции не допускают установку
ПК>// отрицальтного значения свойству Val.
ПК>//
ПК>#define A_ERROR_INVALID_VAL  ((ErrorCode)-1)

ПК>typedef struct Atag A;

ПК>A*        create_A(void);
ПК>void      delete_A(A*);
ПК>int       A_getVal(A*);
ПК>ErrorCode A_setVal(A*, int);
ПК>

У Вас тут Atag не объявлен, и я не совсем уверен, что в Си можно писать struct Atag; чтобы объявить имя, но это неважно.

ПК>Файл с реализацией:

ПК>
ПК>. . .

ПК>struct Atag
ПК>{
ПК>   int _val;
ПК>};

ПК>A* create_A(void)
ПК>{
ПК>   A* a = (A*)malloc(sizeof(A));
ПК>   return a;
ПК>}

ПК>void delete_A(A* a)
ПК>{
ПК>   free(a);
ПК>}

ПК>int A_getVal(A* a)
ПК>{
ПК>   return a->_val;
ПК>}

ПК>ErrorCode setVal(A* a, int val)
ПК>{
ПК>   if (val < 0)
ПК>     return A_ERROR_INVALID_VAL;

   a->>_val = val;
ПК>   return A_OK;
ПК>}
ПК>


ПК>Использование:

ПК>
ПК>int main()
ПК>{
ПК>   A*        a;
ПК>   ErrorCode err_code;

ПК>   a = create_A();
ПК>   if (!a)
ПК>     return -1;

ПК>   err_code = 0;

ПК>   . . .

ПК>   if (err_code != A_OK)
ПК>     err_code = A_setVal(a, 123);  // OK

ПК>   if (err_code != A_OK)
ПК>     err_code = A_setVal(a, -123); // Облом в рантайме.

ПК>   if (err_code != A_OK)
     a->>_val = -123;  // Облом во время компиляции.

ПК>   delete_A(a);

ПК>   return err_code == A_OK ? 0 : -1;
ПК>}
ПК>

Ну а теперь сам вопрос: А слабо Вам с Вашей инкапсуляцией создать genuine local object? Без всяких там хэндлов или указателей... Создавать объект на хипе только для того, чтобы скрыть его детали — изврат.

>> Не думаю, что этот пример был действительно нужен.

Оказалось, что нужен т.к. позволил понять в чем заблуждается Павел, .

ПК>Отчего же, он вполне хорошо проиллюстрировал твою позицию, здорово сэкономив нам время на ненужной риторике.

Которая (позиция) тем не менее оказалась правильной (в отличии от Вашей).

ПК>Как видишь, C вполне позволяет писать код, эквивалентный в отношении инкапсуляции коду на C++.

Как видите, Павел, Си вполне не позволяет создать локальный объект, который бы делал "то, что нужно" в ответ на посылку какого-нибудь сообщения, выражаясь ООП терминологией.

ПК>Скажем, та же Win API в этом отношении вполне в порядке.

Win API Вы привели совершенно не к месту. Там структуры данных ядра находятся в виртуальном адресном пространстве самого ядра, и даже зная их описание, Вы все равно бы ничего не смогли сделать с ними. Использование хэндлов или дескрипторов является, имхо, единственным естественным решением для доступа к этим структурам данных, а не по-тому что "так инкапсуляция происходит лучше." Попробуйте использовать наследие, инкапсуляцию и полиморфизм в С++, чтобы добиться такого же эффекта, что и Win API со своими хэндлами, и увидите, что не так-то это и легко. Поэтому я и использую слово "естественный."

ПК>Это в теории. На практике можно наблюдать, что многие библиотеки и API, написанные на C, лучше скрывают детали своей реализации, чем аналогичные библиотеки и API на C++.

Это чем же? Забудьте о Win API т.к. говоря о них, мы говорим о структурах данных ядра и другом адресном пространстве...

Есть библиотеки на Си которые извращаются точно так же как и извратились Вы и возвращают либо какой-нибудь хэндл или указатель на объект в адресном пространстве процесса, но делается это не потому, что "инкапсуляция в Си лучше," а за неимением в Си того, что предоставляет нам С++ со своими public, protected и private. С++ в этом плане идет на шаг дальше, и поэтому Влад и говорит, что в Си инкапсуляция примитивнее чем в С++.

ПК>Попробуй, например, доступиться к внутренним структурам Windows — вряд ли это получится сделать легко: Win API достаточно хорошо изолирует тебя от внутренних деталей.

Еще бы! Структуры данных-то находятся в адресном пространстве ядра, . См. мое объяснение выше.

ПК>А теперь давай посмотрим, скажем, на MFC... Много переменных-членов public, protected, не говоря уже о различных "внутренних" функциях с доступом public, включенных в интерфейс класса просто потому что они нужны самой MFC.

MFC не является примером для подражания, и то, о чем Вы говорите сейчас, говорит о плохом дизайне а не о поддержке инкапсуляции в языках Си и С++.

ПК>На C++ легче организовать сокрытие данных (вообще-то это вовсе не эквивалентно инкапсуляции, но на этом можно сейчас не останавливаться). Но это вовсе не означает, что сокрытие данных будет практически более эффективно, чем в C.

Не совсем понимаю, что Вы имеете здесь в виду под эффективностью, но, как я уже заметил, с Вашей инкапсуляцией на Си вы не можете создать локальный объект, который бы просто "делал свою работу." А создовать объект на хипе, чтобы скрыть его данные — это просто изврат.

> Сравнение не корректно. Команда, которая делала API Windows — была на несколько порядков опытнее <...>

ПК>Я с этим не спорю. Я только привел пример того, что на C вполне возможно писать, не выпячивая детали реализации наружу; плюс пример того, что на C++ инкапсуляция автоматически "сама собой" тоже не возникает. Именно квалификация разработчиков, с моей точки зрения, и определяет "степень инкапсулированности" того, что получится в результате. И именно поэтому я скептически отношусь к заявлениям, скажем, о "большем совершенстве С+ с точки зрения инкапсуляции".
Так-то оно так, но вот С++ больше помогает программисту избежать ошибок (своими private и public) а вот Си — нет.

09.11.04 15:58: Перенесено из 'C/C++'
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.