Комментарии 54
Реализация инструментов ООП в языках, для этого не предназначенных (привет Fortran'у) — это конечно полезно с точки зрения образования.
А что насчет практической пользы?
А что насчет практической пользы?
+1
В общем-то, ООП на C не новость. Ярчайший пример — GTK+. И в нем используются виртуальные функции (хотя, несколько по-другому).
+1
о GTK+ не знал, спасибо! Интересно, чем их не устроило ООП в C++?
(Вики говорит в пользу C только про «желание легко строить интерфейсы для других языков программирования»)
(Вики говорит в пользу C только про «желание легко строить интерфейсы для других языков программирования»)
+2
Objective C туда же. Там, кстати, все функции являются виртуальными.
-1
Ну, Objective C — полноценный язык. А GTK+ — просто библиотека, без всяких расширений.
+1
в ObjC виртуальные функции обрабатываются компилятором и рантаймом, разработчику не нужно заполнять руками какие-то странные структуры, как в примере из топика
+3
А вы знаете чем за такие соменительные преимущества приходится платить? Рантайм связывание всегда и везде ведет к нехилой потере скорости, кроме того для универсальности (Я полагаю именно так) введено общение с обьектом только через укащатель, а сам обьект создается динамически. За год работы с этой дрянью я понял только одно — этот язык хорошо решает те проблемы которые в других языках програмирования не встречаются.
0
Самая соль ООП для С реализована в библиотеке Glib, которую GTK просто использует.
+2
А что такое «язык, не предназначенный для ООП», позвольте узнать?
В ООП-стиле можно писать на любом языке.
В ООП-стиле можно писать на любом языке.
+1
Очевидно это язык, не имеющий встроенных синтаксических средств для ООП.
Про то, что писать можно на любом, это конечно да. Даже на Brainfuck, полагаю :)
Про то, что писать можно на любом, это конечно да. Даже на Brainfuck, полагаю :)
+1
Ну по этой логике, Сысоеву ни в коем случае не следовало бы писать nginx на Си. Ведь немало языков предоставляют возможности для организации параллельных легковесных задач и их координации. А в Си ничего подобного нет, следовательно он не предназначен для данной задачи.
+1
Видимо, необходимо доступнее изложить мою мысль.
Так вот, при выборе языка под задачу, учитывается разное. Производительность, скорость разработки, наличие библиотек и так далее. Могут быть какие-то специфические требования.
Наличие поддержки ООП в языке — безусловно плюс, по шкале «скорость разработки». Но если есть другие критерии, помимо скорости разработки, тогда внезапно может выиграть язык без встроенной поддержки ООП.
Еще раз — в ООП стиле можно писать на любом языке. Есть языки в большей или меньшей степени приспособленные к этому. Совсем непригодных нет.
Так вот, при выборе языка под задачу, учитывается разное. Производительность, скорость разработки, наличие библиотек и так далее. Могут быть какие-то специфические требования.
Наличие поддержки ООП в языке — безусловно плюс, по шкале «скорость разработки». Но если есть другие критерии, помимо скорости разработки, тогда внезапно может выиграть язык без встроенной поддержки ООП.
Еще раз — в ООП стиле можно писать на любом языке. Есть языки в большей или меньшей степени приспособленные к этому. Совсем непригодных нет.
0
Согласен, что слово не предназначен не совсем верно передает идею моего высказывания. Я недоумевал именно об ООП в C, в то время как уже существует, на мой взгляд, общепризнанный и успешный его наследник с имплементацией ООП — C++
Что касается вашего примера, то настоящий профессионал вполне может рассчитывать на то, что способен реализовать, например, «организацию параллельных легковесных задач и их координации» лучше, чем в существующих на данный момент решениях, и избрать как раз подходящий для таких фундаментальных задач чистый Си. Возможно, и создание GTK+ объясняется именно этим.
Что касается вашего примера, то настоящий профессионал вполне может рассчитывать на то, что способен реализовать, например, «организацию параллельных легковесных задач и их координации» лучше, чем в существующих на данный момент решениях, и избрать как раз подходящий для таких фундаментальных задач чистый Си. Возможно, и создание GTK+ объясняется именно этим.
0
ядро Линукса передаёт вам привет
+3
НЛО прилетело и опубликовало эту надпись здесь
А что мешает использовать в ядре С++ и виртуальные функции?
0
НЛО прилетело и опубликовало эту надпись здесь
exceptions и RTTI можно не использовать.
Бардак в ABI нас не волнует, если мы наружу не будем выставлять плюсовые интерфейсы.
Чем мешает недетерминированность вызова конструкторов глобальных объектов? Если нужно, чтобы было детерминированно — можно обойтись без глобальных объектов в конце концов.
Ну и вот объясните, зачем выдумывать виртуальные функции на С, когда можно было взять С++, отказаться от всего вышеперечисленного, но пользоваться виртуальными функциями по-человечески?
Бардак в ABI нас не волнует, если мы наружу не будем выставлять плюсовые интерфейсы.
Чем мешает недетерминированность вызова конструкторов глобальных объектов? Если нужно, чтобы было детерминированно — можно обойтись без глобальных объектов в конце концов.
Ну и вот объясните, зачем выдумывать виртуальные функции на С, когда можно было взять С++, отказаться от всего вышеперечисленного, но пользоваться виртуальными функциями по-человечески?
+3
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
>И что получим в результате? Убожество под названием С с классами.
… которое при этом всё равно будет куда элегантнее для поставленной в топике задачи, чем ванильный C99.
… которое при этом всё равно будет куда элегантнее для поставленной в топике задачи, чем ванильный C99.
+3
Зачем запрещать STL, наследование, перегрузку и шаблоны? Если с RTTI и исключениями есть реальные проблемы то с остальным то что не так? И даже если отказаться от всего остального все равно останется полноценный ООП-язык.
-1
Ну RTTI и ABI — это понятно в чем проблема, но с exceptions то что такого?
0
Суть виртуальных функций не в том, что их можно переопределить, а в том, что они всегда вызываются от действительного инстанса класса.
ClassA *instance = new ClassB();
std::cout << instance->get() << std::endl; // выведет 9, а без модификатора virtual было бы 11
+5
Суть примера в начале статьи не в вызове метода get(), а в вызове соответствующего метода set() в теле метода get().
Хотя трактовка виртуальной функции в статье, действительно, немного странная.
Хотя трактовка виртуальной функции в статье, действительно, немного странная.
+2
Да, тоже немного удивился отсутствию слова «полиморфизм» в статье про виртуальные функции.
0
Автор статьи порадовался переводу: twitter.com/#!/milot/status/172245024837349378 :)
+1
«В C не существует указателя this, который указывал бы на вызывающий объект. Я назвал параметр та́к, для того чтобы сымитировать использование указателя this в C++»
Отличное решение — если теперь файл когда-либо потребуется скомпилировать С++ компилятором, нас ждет облом из-за ключевого слова this. Что не так уж и невероятно — представьте себе, что этот код попал в хидер Си-шной библиотеки, которую нужно использовать из C++.
Отличное решение — если теперь файл когда-либо потребуется скомпилировать С++ компилятором, нас ждет облом из-за ключевого слова this. Что не так уж и невероятно — представьте себе, что этот код попал в хидер Си-шной библиотеки, которую нужно использовать из C++.
0
В Quake 3 у ID Software как раз меню подобным извращение было реализовано. Была структура с указателями на функции и они разные функции присваивали в инициализацие меню.
0
Люблю С за то, что на нём можно сделать виртуальный конструктор, события и св-ва, в отличие от С++.
-3
Несколько дополнений. В vtable конструктор не нужен, т.к. виртуальных конструкторов — не бывает, и компилятор знает какой именно вызывать на этапе компиляции. Пример можно было бы дополнить, как раз виртуальным деструктором.
Также на практике наследование представлено в виде дублирования полей, а не как поле типа базового класса. Для примера вспомните виртуальное наследование.
В дополненение ваш пример можно было расширить созданием/уничтожением глобальных объектов, и использованием new/delete.
Сам написал подобную статью несколько месяцев назад, но отверстать так руки не дошли. Там также описано про RTTI, и исключения средствами С.
Также на практике наследование представлено в виде дублирования полей, а не как поле типа базового класса. Для примера вспомните виртуальное наследование.
В дополненение ваш пример можно было расширить созданием/уничтожением глобальных объектов, и использованием new/delete.
Сам написал подобную статью несколько месяцев назад, но отверстать так руки не дошли. Там также описано про RTTI, и исключения средствами С.
0
На нечто такое я натыкался в библиотеке ffmpeg, которая при ближайшем расмотрении оказалась написаной в основном на чистом Си.
0
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Виртуальные функции в C