Наследование в С: хорошо, плохо или другое? - PullRequest
4 голосов
/ 19 января 2012

У нас есть большая база кода C, которая была разработана в течение нескольких десятилетий.Одной из особенностей кода является большая зависимость от указателей функций и псевдо-наследования.Идиома (как обсуждено здесь ) выглядит следующим образом:

typedef struct twod_ {
    double x, y;
} twod;

typedef struct threed_ {
    twod super;
    double z;
} threed;

threed *point_3d;
twod *point_2d = (twod *)point3d;

В какой момент point_2d->x и point_3d->x являются одним и тем же блоком памяти.

Myвопросы:

  • Эта идиома все еще популярна в современном производственном коде?(Любые рекомендуемые примеры с открытым исходным кодом)
  • Этот код имеет требование к производительности - помогает ли эта идиома в скорости и / или использовании памяти?
  • Способ, которым он был реализован (или из-зав течение многих лет раздувания кода) теперь это похоже на спагетти-код - вообще говоря, это проблема с реализацией или идиома?Или, иначе говоря, в идеальном мире, 500 тыс. LOC с такой идиомой быстро поняли бы?

Конечно, пословица «если она не сломалась, не чини ее» была быхороший, чтобы иметь в виду;однако, на данный момент это не очень помогает нам, поэтому мы думаем, что нам, возможно, придется углубиться в рефакторинг ...

Спасибо!

Ответы [ 4 ]

2 голосов
/ 19 января 2012

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

Для меня флагманская реализация "C с классами" с открытым исходным кодом, вероятно, GTK + , в частности модуль gobject .

1 голос
/ 19 января 2012

Это будет работать, но вы должны иметь в виду, что компилятор не будет ничего предупреждать / говорить вам о проблемах, связанных с доступом к переменным или чем-то подобным. Этот метод небезопасен, потому что иногда это явное приведение может быть злым. Возьмите этот пример в качестве примера:

typedef struct _A
{
    double x, y;
} A;

typedef struct _B 
{
    A super;
    double z;
} B;

typedef struct _C 
{
    A super; // we wanted B, but wrote A by mistake
    double w;
} C;

C* c;
B* b = (B*)c;

// will write to C::w instead of B::z and no one will warn you about this.
// you'll need to track this by hand after your application crashes.
b->z = 1234; 

Этот тип вещей может легко посадить самолет на землю. :)

Что касается производительности, то в конечном итоге будет сделано то же самое, как если бы вы взяли указатель на super вручную (более безопасно, чем приведение):

A* a;
B* b = &a->b; 

Также я не думаю, что это популярно в наши дни (по крайней мере, не для таких молодых программистов, как я, которые стали программировать на более современных компиляторах)

Кроме того, компилятор C ++ является опцией? В наши дни более современные компиляторы, которые допускают наследование структуры - лучше, чем приведение таким образом.

0 голосов
/ 19 января 2012

Эта идиома все еще популярна в современном производственном коде? (Любой рекомендуемые примеры с открытым исходным кодом)

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

Этот код имеет требование к производительности - помогает ли эта идиома в скорости и / или использовании памяти?

Это, безусловно, не сделает код более эффективным, чем структура, содержащая все 3 члена. В худшем случае наследие сделает код менее эффективным. Лучший способ узнать это - разобрать выходные данные компилятора для вашей конкретной платформы и убедиться в этом.

... это проблема с реализацией или идиома?

Наследование в целом следует использовать осторожно, наследование ради наследования не наполняет цели. Это верно для всех ОО языков.

Лично я считаю, что эта конкретная идиома и подобные попытки включить умеренно полезные функции OO в C проблематичны. Главным образом потому, что они значительно усложняют программу. Подобные вещи проповедовались в книге «Объектно-ориентированное программирование с использованием ANSI-C» (Аксель-Тобиас Шрайнер, выпущенный в начале 90-х). Лично я нахожу большинство вещей в этой книге довольно ужасными.

в идеальном мире, 500K LOC с такой идиомой быстро понял?

Это гораздо больше зависит от структуры программы, структуры файлов и стандартов кодирования, чем от этой маленькой идиомы. Хотя, конечно, 500k loc не будет быстро понят, даже если программа является самой современной.

0 голосов
/ 19 января 2012

Как (почти) все в C, если вы знаете, что делаете, это нормально.Но имейте в виду, что проблемы могут возникнуть очень легко - например, если у вас есть массив threed, вы не можете привести его к массиву twod.(доступ к членам этого приведенного массива - неопределенное поведение)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...