LINUX.ORG.RU

Деструкторы не нужны (?)

 


0

5

Тут в соседней теме один анон сказанул следующее:

Дело не в том. Сишка, она про написание руками + можно навесит абстракций, аки глиб/гобджект. Кресты же — изначально нагромождение абстракций со строками, срущими в кучу, функциональными объектами, методами, вызывающимися неявно (например, деструкторы, на которые жаловался кармак) и проч

Собственно, хотелось бы поговорить о выделенном.

Антон прикрылся ссылкой, по которой про деструкторы я так ничего и не нашёл. Более того, в твиттере Кармака всё выглядит с точностью до наоборот — https://twitter.com/id_aa_carmack/status/172340532419375104

RAII constructor / destructor pairing and templates for type safe collections are pretty high on my list of C++ benefits over C

Кто прав? Кто виноват? И нужны ли в итоге C++ деструкторы?

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

Я делал этот пример на скорую руку, чтобы показать основную идею, что нет наследования интерфейса от реализации. Что конкретно тут небузопасно? Мне естественно, лень городить полноценную либу. Накидал быдлокодский прототип за две минуты. Если скажешь, что не так, то отвечу как разрулить, иначе просто метание какашками.

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

Ладно, не бомби. Я хотел написать «чуть ли не», а не «фактически».

Так или иначе, первый раз в жизни соглашусь с tailgunner (он случайно выдал не бред): твой подход — это унылый ужас.

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

Конкретные недостатки привести сможешь? Почему в более современных языках аля c# это считается нормой? А в с++ - это тихий ужас?

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

Почему в более современных языках аля c# это считается нормой? А в с++ - это тихий ужас?

«В более современных языках аля c# это» напрямую пришло именно из С++.

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

Устаревшие обертки (QT5 is not yet supported)

Верно :-)

битые ссылки

Что-что? :-)

отсутствие нормальной документации и примеров (а значит идти по граблям и узнавать, что не поддерживается или криво сделано, предлагается пользователю) - да, это всегда есть у программистов на лиспе

То же самое есть у программистов на цепепе и на питоне :-)

Вот лисп (пример взят по ссылке):
Вот питон:

Что же ты не запостил сюда листинг кода на цепепе, а сразу за питоном побежал? :-) И ещё запости сюда скорости работы лиспа и питона — банально посчитай сумму первых N натуральных чисел :-) Ноу комментс у него :-) Лол :-)

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

И ещё запости сюда скорости работы лиспа и питона — банально посчитай сумму первых N натуральных чисел

Ты только что всю суть лиспа.

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

запости сюда скорости работы лиспа и питона

Если бы только в скорости было дело, все бы писали на ассемблере

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

Что-что?

Ссылки битые на туториал, скачивание и пр.

То же самое есть у программистов на цепепе и на питоне

Есть, но у них это не является нормой.

Что же ты не запостил сюда листинг кода на цепепе, а сразу за питоном побежал?

Потому-что показывал разницу между нормальной оберткой и тем, что привыкли есть лисперы. А на С++ это будет так:

struct Canvas: QWidget {
    void paintEvent( QPaintEvent* ) {
        QPainter p( this );
    }
}

И ещё запости сюда скорости работы лиспа и питона — банально посчитай сумму первых N натуральных чисел

Ну банально так банально:

n*(n+1)/2

Можешь мерять.

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

нормальной оберткой

Ты правда сейчас пытаешься бидон противопоставить лиспу в чуть ли не единственной категории, в которой лисп действительно что-то из себя представляет?

Почему commonqt такой недоделанный это отдельный вопрос, конечно.

anonymous
()
Ответ на: комментарий от tailgunner

А что такое, в C# есть свободные функции?

А почему их нет? Потому что свободные функции - это изменения интерфейса, поведения. Надо изменить интерфейс, поведение - пили новый класс через наследование/агрегирование.

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

в чуть ли не единственной категории, в которой лисп действительно что-то из себя представляет?

Это категория «считаем сумму чисел»?

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

Плохой, негодный петросян.

Это категория «синтаксическая абстракция».

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

Ссылки битые на туториал, скачивание и пр.

А, ну это не проблема для хакеров :-)

Есть, но у них это не является нормой.

А что у них является нормой? :-) Четверть века посвятить глубинному изучению C++, чтобы наконец постичь некоторые стороны ремесла написания корректного кода? :-)

Ну банально так банально:
n*(n+1)/2
Можешь мерять.

Я просил скорость, а ты написал какую-то дробь :-) Ну бывает, конечно, это тебе не деструкторы с noexcept писать и не перетасовывать код, чтобы он был exception-safe :-)

anonymous
()
Ответ на: комментарий от Dudraug

А что такое, в C# есть свободные функции?

А почему их нет?

По маркетинговым причинам. Во времена появления C# было модно быть Ъ-ООП, а в нем нет свободных функций. Правда, static-члены оставили %)

Надо изменить интерфейс, поведение - пили новый класс через наследование/агрегирование.

Мде. Менять интерфейсы ты сам запрещаешь или просто тебе запретили? А запилить новую функцию кто или что запретил?

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

Если бы только в скорости было дело, все бы писали на ассемблере

А сколько раз доводилось слышать, что C++ берут когда скорость нужна :-) А ты сейчас про ассемблер зачем-то заговорил :-) Ты говори за скоростной C++, тем более в треде про деструкторы :-) Или нечего сказать? :-)

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

А сколько раз доводилось слышать, что C++ берут когда скорость нужна

Слышал звон, да не знаешь, где он.

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

Ты правда сейчас пытаешься бидон противопоставить лиспу в чуть ли не единственной категории, в которой лисп действительно что-то из себя представляет?

Представлять что-то в теории и на практике - огромная разница. А реальность такова, что DSL-и на DSL-ях в лиспе гораздо чаще встречаются в рассказах фанатиков чем в реальности и тем более в серьезном коде.

Почему commonqt такой недоделанный это отдельный вопрос, конечно.

Это не commonqt такой недоделанный, это обычное состояние для общелиспа - помойка вместо библиотек.

anonymous
()
Ответ на: комментарий от tailgunner

Правда, static-члены оставили %)

Статик члены имхо вполне себе ООП, если их правильно готовить. А не юзать как аналог функциям в чистом си.

Мде. Менять интерфейсы ты сам запрещаешь или просто тебе запретили? А запилить новую функцию кто или что запретил?

Мы вроде говорили о сформировавшемся интерфейсе библиотечной функции. У класса есть декларированный интерфейс, есть его контракт. Добавление функций -> его нарушение. К примеру у тебя класс A библитечный принимал функции интерфейса IA, но ты решил добавить специальное расширение для наследника интерфейса IA, а потом или забыл об этом или твой коллега не знал и напиал код с расчетом на повдение скажем operator<<(IA&), а на деле поведение другое. Контракт нарушен. Хотя уже написан код расчитывающий на этот интерфейс и на это поведение.

http://coliru.stacked-crooked.com/a/b6f3e842c0a81346

Запусти, а потом закоменть свободную функцию.

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

Слышал звон, да не знаешь, где он.

Это слив, извини :-)

anonymous
()
Ответ на: комментарий от Dudraug

По хорошему функции принимающие некий объект, должны быть или членами того же класса, или некоего другого, на крайний случай (редкий) статическими. Свободные функции затрудняют понимание и осознание чужого кода.

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

Нет, ты просто балаболка :-)

Ну давай, выдави ещё что-нибудь из себя, хотя бы ради приличия :-) Что-то ты прям уж сухо совсем :-) Лол :-)

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

Представлять что-то в теории и на практике - огромная разница. А реальность такова, что DSL-и на DSL-ях в лиспе гораздо чаще встречаются в рассказах фанатиков чем в реальности и тем более в серьезном коде.

Что за серьёзный код такой? :-) Давай, покажи серьёзный код :-) Код браузера или офиса? :-)

Это не commonqt такой недоделанный, это обычное состояние для общелиспа - помойка вместо библиотек.

Библиотеки уже вышли из моды :-) Сейчас всё доступно в интернете :-) Лол :-)

anonymous
()
Ответ на: комментарий от Dudraug

Статик члены имхо вполне себе ООП

А, окей. Ну, тогда в C# никто не использует свободные функции потому, что их нет.

Менять интерфейсы ты сам запрещаешь или просто тебе запретили? А запилить новую функцию кто или что запретил?

Мы вроде говорили о сформировавшемся интерфейсе библиотечной функции.

Вроде нет. Но я спросил, что мешает тебе создать новую функцию. Не метод класса, а функцию.

У класса есть декларированный интерфейс, есть его контракт. Добавление функций -> его нарушение. К примеру у тебя класс A библитечный принимал функции интерфейса IA, но ты решил добавить специальное расширение для наследника интерфейса IA, а потом или забыл об этом или твой коллега не знал и напиал код с расчетом на повдение скажем operator<<(IA&), а на деле поведение другое. Контракт нарушен

Такое впечатление, что ты пишешь с холодильника и сэкономил половину слов, которые содержали смысл.

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

Что за серьёзный код такой? :-) Давай, покажи серьёзный код :-) Код браузера или офиса? :-)

https://github.com/slime/slime

Например, я думал из контекста будет понятно, что речь про лисп, хотя, конечно, найти что-то серьезное опенсорсное на нем не так уж и просто.

Библиотеки уже вышли из моды :-) Сейчас всё доступно в интернете :-) Лол :-)

Унылый из тебя клоун.

anonymous
()
Ответ на: комментарий от tailgunner

Такое впечатление, что ты пишешь с холодильника и сэкономил половину слов, которые содержали смысл.

Пример кода по линку. Заметь, я не говорю, что свободные функции вообще не нужны, это хорошо, что в языке они есть. Но я бы их оставил на случай, когда без них код будет сложнее для понимания, сильно больше по объему. Для меня задача создание функционала для сериализации вектора требует создание нового класса SerializableVector, а не расширения интерфейса существующего класса.Возможно для нормальной объектной модели еще пару классов потребуется вроде ObjectSerializer<SerializableVector>.

Dudraug ★★★★★
()
Последнее исправление: Dudraug (всего исправлений: 2)
Ответ на: комментарий от anonymous

http://github.com/slime/slime

Эта поделка хакеров для хакеров :-)

Унылый из тебя клоун.

Ой как быстро же ты приуныл :-) Лол :-)

anonymous
()
Ответ на: комментарий от Dudraug

Пример кода по линку

По коду пример «во, смотрите, я сделал новый контракт, он другой». Что считается сломом и как свободные функции ухудшили или улучшили ситуацию - непонятно.

Для меня задача создание функционала для сериализации вектора требует создание нового класса SerializableVector, а не расширения интерфейса существующего класса.Возможно для нормальной объектной модели еще пару классов потребуется вроде ObjectSerializer<SerializableVector>.

Опять же - чем это лучше создания функции serialize_vector<T>?

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

Опять же - чем это лучше создания функции serialize_vector<T>?

Тем, что интерфейс в одном месте описан. Чем меньше интерфейс разбросан по коду, тем проще код понимать (если ты не автор кода и видишь его впервые, а задачу надо сделать вчера).

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

Чем меньше интерфейс разбросан по коду, тем проще код понимать (если ты не автор кода и видишь его впервые, а задачу надо сделать вчера).

Есть IDE вообще-то :-) Ну это кто своё время бережёт и готов заплатить заслуженные деньги разработчикам :-) Для остальных - проблема, да :-)

anonymous
()
Ответ на: комментарий от Dudraug

Опять же - чем это лучше создания функции serialize_vector<T>?

Тем, что интерфейс в одном месте описан.

В случае template<class T> serialize_vector(const T&) - тоже. Просто он не в классе, а в заголовочном файле.

Чем меньше интерфейс разбросан по коду

(пожимая плечами) Реальные интерфейсы состоят не из одного класса. При желании их можно разбросать очень далеко.

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

Опять же - чем это лучше создания функции serialize_vector<T>?

Одно г...

Для вектора должно быть как-нибудь так

template <typename T>
void serialize(buffer&, const std::vector<T>&)

anonymous
()
Ответ на: комментарий от Dudraug

Тем, что интерфейс в одном месте описан.

Так и получается со свободной шаблонной функцией. Интерфейс описан в одном месте. Плюс аффтар интерфейса предоставляет реализации для сериализации примитивных типов.

А для своих типов ты запиливаешь свою перегрузку/свой шаблон функции.

Интерфейс не размазан, размазаны реализации. Что естественно.

anonymous
()
Ответ на: комментарий от tailgunner

Пожалуйста, не бомби. Ты на самом деле предложил г. То, что предложил я отличается принципиально.

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

Пожалуйста, не бомби

Пожалуйста, не проецируй.

Ты на самом деле предложил г

В рамках дискуссии твое предложение - ровно такое же г.

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

В рамках дискуссии твое предложение - ровно такое же г.

Нет

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

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

всем пофиг.

Как минимум тебе — нет

Как раз мне пофиг (я вообще сериализацию шаблоном класса делаю), но я вежливый и отвечаю даже тебе.

Но продолжать сраться — скучно...

Следующий раз попробуй не начинать.

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

я вообще сериализацию шаблоном класса делаю

Да, шаблон структуры со статическими функциями — это неплохой подход. Проще задетектить, что для данного типа не реализована сериализация.

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

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

Отведайте царского кода

// ---------------------------- provided by library ----------------------------
#include <iostream>
#include <type_traits>
namespace serialization_lib {
using buffer = std::ostream;

template<class T>
struct serializable {
	static const bool implemented = false;
	static void serialize(buffer&, const T&);
};

template<class T>
std::enable_if_t<serializable<T>::implemented>
serialize(buffer& buf, const T& obj)
{
	serializable<T>::serialize(buf, obj);
}

// specializations for fundamental types
template<>
struct serializable<size_t> {
	static const bool implemented = true;
	static void serialize(buffer& buf, size_t obj) { buf << obj; }
};
}
// -----------------------------------------------------------------------------


// --------------------------- overload for our type ---------------------------
// #include <serialization_lib>
#include <vector>
#include <type_traits>
template<class T>
struct serialization_lib::serializable<typename std::vector<T>> {
	static const bool implemented = true;

	static
	std::enable_if_t<serializable<T>::implemented>
	serialize(buffer& buf, const std::vector<T>& vec)
	{
		using serialization_lib::serialize;

		serialize(buf, vec.size());
		for (const auto& v : vec)
			serialize(buf, v);
	}
};
// -----------------------------------------------------------------------------


#include <vector>
#include <iostream>
int main()
{
	using serialization_lib::serialize;

	std::vector<size_t> vec = {1, 2, 3};
	serialize(std::cout, vec);

	std::cout << std::endl;

	std::vector<std::vector<size_t>> vec2 = {vec};
	serialize(std::cout, vec2);
}

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

Теперь то, наверное, Торвальдс считает C++ хорошим языком :-)

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

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

в целом уже показывал - прокидываю наверх.

https://github.com/dzidzitop/ant_modular/blob/master/src/java/afc/ant/modular...

если бы было несколько ресурсов, которые нужно трекать, то было бы что-то типа:

resource1 = getResource();
try {
    /* some code */

    resource2 = getOtherResource();
    try {
        /* some code */
    } finally {
        resource2.release();
    }

    /* some code */
} finally {
    resource1.release();
}

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

пример с дверью не очень понял.

dzidzitop ★★
()
Последнее исправление: dzidzitop (всего исправлений: 3)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.