OberonCore https://forum.oberoncore.ru/ |
|
ГудвинЪ. Великий и ужасТный! https://forum.oberoncore.ru/viewtopic.php?f=26&t=1381 |
Страница 1 из 2 |
Автор: | Wlad [ Четверг, 05 Март, 2009 12:47 ] |
Заголовок сообщения: | ГудвинЪ. Великий и ужасТный! |
Набрёл в Сети вот на это: http://habrahabr.ru/blogs/cpp/53576/ Опять вспомнилось, взгрустнулось, пожалелось о массах заблудшихЪ... |
Автор: | Alexey Veselovsky [ Четверг, 05 Март, 2009 15:40 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Набрёл в Сети вот на это: http://habrahabr.ru/blogs/cpp/53576/ Опять вспомнилось, взгрустнулось, пожалелось о массах заблудшихЪ... А что собственно не так? Ты пользователь класса A, видишь только его спецификацию. Было бы странно предположить что в функцию вдруг передастся что-то отличное от 10. Если пользователю не нравится дефолтная десятка, то он волен задать своё значение. Ни о каких двадцатках он не знает и знать не может. Также он не знает метод какого конкретного класса вызовется, ибо не его это дело. Полиморфизмъ. Если бы функция вызвалась бы с параметром 20, то это было бы нарушением контракта. |
Автор: | Wlad [ Четверг, 05 Март, 2009 15:51 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Alexey Veselovsky писал(а): Владимир Лось писал(а): Набрёл в Сети вот на это: http://habrahabr.ru/blogs/cpp/53576/ Опять вспомнилось, взгрустнулось, пожалелось о массах заблудшихЪ... А что собственно не так? Ты пользователь класса A, видишь только его спецификацию. Было бы странно предположить что в функцию вдруг передастся что-то отличное от 10. Если пользователю не нравится дефолтная десятка, то он волен задать своё значение. Ни о каких двадцатках он не знает и знать не может. Также он не знает метод какого конкретного класса вызовется, ибо не его это дело. Полиморфизмъ. Если бы функция вызвалась бы с параметром 20, то это было бы нарушением контракта. А если я - ПОЛЬЗОВАТЕЛЬ КЛАССА В??? Как? Практически ВСЕ, кого спросил (кроме двух), указали 20. Один сказал 10, потому, что новичок и неправильно понимал поведение и правила перекрытия виртуальных функций в Си++, второй - до этого прочитал статью. Все остальные (даже сторонники и приверженцы Си++), заметили "разветвлённость" понятийного момента (по правилам виртуализации и по умолчаниям в аргументах). Все хором сошлись на "хорошо в пятнадцати строчках! А попробуй найти лопух в десятках тысячах строк проекта, ежели чаво!..." Наше - вам! ЗЫ Кроме того, уж извините, но при таком раскладе, как в примере, я НИКАК не могу быть "пользователем класса А"... Подумайте - почему? ![]() |
Автор: | Alexey Veselovsky [ Четверг, 05 Март, 2009 16:07 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Цитата: Кроме того, уж извините, но при таком раскладе, как в примере, я НИКАК не могу быть "пользователем класса А"... Подумайте - почему? Потому, что сами создали экземпляр B? |
Автор: | Alexey Veselovsky [ Четверг, 05 Март, 2009 16:09 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Цитата: А если я - ПОЛЬЗОВАТЕЛЬ КЛАССА В??? Как? А если вы пользователь класса B, то будет 20. Что не так? |
Автор: | Geniepro [ Четверг, 05 Март, 2009 16:11 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Да, как хорошо, что в том быдлокоде, которым я сейчас отягощён, нет таких наворотов -- ни виртуальных функций, ни перегрузки операторов, ни аргументов по умолчанию, ни шаблонов! А то я бы повесился! ![]() |
Автор: | Vlad [ Четверг, 05 Март, 2009 19:08 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Набрёл в Сети вот на это: http://habrahabr.ru/blogs/cpp/53576/ Опять вспомнилось, взгрустнулось, пожалелось о массах заблудшихЪ... Лично у меня никаких проблем с этим примером не возникло. Достаточно представлять (в общих чертах) как реализуются виртуальные функции в C++ и хотя бы раз попытаться сделать указатель на функцию с дефолтовым аргументом. P.S. Хотя конечно я бы предпочел, чтобы компилятор ругался в таких случаях (у него для этого все есть). |
Автор: | Wlad [ Четверг, 05 Март, 2009 23:36 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Alexey Veselovsky писал(а): Цитата: А если я - ПОЛЬЗОВАТЕЛЬ КЛАССА В??? Как? А если вы пользователь класса B, то будет 20. Что не так? Это Вы имеете, конечно в виду, что у меня переменная указатель будет типа указателя на класс В? ЕЩЁ СМЕШНЕЕ, ЕЙ БОГУ! ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Автор: | Alexey Veselovsky [ Пятница, 06 Март, 2009 00:25 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Alexey Veselovsky писал(а): Цитата: А если я - ПОЛЬЗОВАТЕЛЬ КЛАССА В??? Как? А если вы пользователь класса B, то будет 20. Что не так? Это Вы имеете, конечно в виду, что у меня переменная указатель будет типа указателя на класс В? ЕЩЁ СМЕШНЕЕ, ЕЙ БОГУ! ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Я безусловно рад что вам весело, однако не поделитесь ли поводом столь бурного веселья? Хотелось бы тоже порадоваться. |
Автор: | Wlad [ Пятница, 06 Март, 2009 01:00 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Alexey Veselovsky писал(а): Я безусловно рад что вам весело, однако не поделитесь ли поводом столь бурного веселья? Хотелось бы тоже порадоваться. Будете также радоваться, когда уясните роль языка, как средства поддержки/"противодействия" проектных(ым) решений(ям). Моё веселье - от осознания (даже на таком маленьком примере!) убожества Си++ именно с точки зрения на него, как на средство проектирования, а не как на инструмент для хитровы..., пардон, изощрённых кодовых примеров, позволяющих показать изворотливость и остроту умища отдельных индивидов. Данный пример совершенно далёк от какой-то реальной работы и проекта. Тем более высока его ценность. Объясняю. А Вы постарайтесь проникнуться. В данном примере я объявляю указатель на А, НО присваиваю ему экземпляр В. То есть само это действие АБСОЛЮТНО ОСМЫСЛЕНО. Причина объявления именно указателя на А может быть только одна (но она не отражена в примере) - где-то есть нечто, что принимает на входе именно указатели на А, как сущности для каких-то обобщённых, абстрактных, довольно высокоуровневых алгоритмов, ничего про детализацию в наследниках или не знающих, или не желающих знать. НО!, Прошу ещё раз вспомнить, что инициализирую-то я мой указатель ссылкой на экземпляр типа В!. И делаю это я (в примере, как части чего-то большего, очевидно!) СОВЕРШЕННО СОЗНАТЕЛЬНО! Но сам смысл введения наследника от А в виде В подразумевает существования чего-то такого, что или уточняется или отличается в наследниках от того же в предках. В данном примере (одним из?) таких видимых явных отличий как раз и является "значение по умолчанию". И, по логике оно там абсолютно правильно стоит. Конечно, можно было бы его неким образом через "задержанную инициализацию в конструкторе наследника" провести, но мы знаем классный механизм и способ - "значение аргумента метода по умолчанию". Кроме того, нам известен общий принцип переопределения и перекрытия виртуальных методов. А ну-ка, объединим наши проектные решения с возможностями языка! Опппа - облом-с! Оказывается, в случае работы с виртуалами, работает нечто, что поддерживает нашу логику (и работает правильно! "по логике" ИСХОДЯ ИЗ ДИНАМИЧЕСКОГО ТЕКУЩЕГО ТИПА ЭКЗЕМПЛЯРА),а вот другая особенность языка, почему-то "оглядывается" на СТАТИЧЕСКИЙ ТИП! И желаемое проектное решение сливается в унитаз... Вот поэтому мне - да - смешно! Я этим убожищем, слава Б-гу! не пользуюсь. |
Автор: | Alexey Veselovsky [ Пятница, 06 Март, 2009 01:15 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Данный пример совершенно далёк от какой-то реальной работы и проекта. Тем более высока его ценность. Объясняю. А Вы постарайтесь проникнуться. В данном примере я объявляю указатель на А, НО присваиваю ему экземпляр В. То есть само это действие АБСОЛЮТНО ОСМЫСЛЕНО. Причина объявления именно указателя на А может быть только одна (но она не отражена в примере) - где-то есть нечто, что принимает на входе именно указатели на А, как сущности для каких-то обобщённых, абстрактных, довольно высокоуровневых алгоритмов, ничего про детализацию в наследниках или не знающих, или не желающих знать. Это действие (приведеённое в примере) абсолютно бессмысленно. Код: void foo(A* p_a) {// что-то тут делаем с А} int main() { B* p_b = new B; foo(p_b); } Нет ни малейшего смысла в указателе p_b типа A*. |
Автор: | Wlad [ Пятница, 06 Март, 2009 01:48 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Vlad писал(а): Лично у меня никаких проблем с этим примером не возникло. Достаточно представлять (в общих чертах) как реализуются виртуальные функции в C++ и хотя бы раз попытаться сделать указатель на функцию с дефолтовым аргументом. Ой-ли?Или это так по мозгам трактором логики Си++ проезжаются? Vlad, с логикой переназначения виртуальных функций все знакомы. Идя от общего к частному, и считая, что таки описание функции-члена принадлежит конкретному классу, почему вдруг, оказывается, что функция назначается динамикой (по таблице виртуальных методов), а назначение значений по умолчанию в аргументах - по статике? Vlad писал(а): P.S. Хотя конечно я бы предпочел, чтобы компилятор ругался в таких случаях (у него для этого все есть). То есть, у вас тоже "червь сомнения есть" и Вы хотели бы тоже не упустить из памяти возможность такого рода "зевка"? ![]() ![]() Кроме того вот это (повторю исчо раз) сильно порадовало: Vlad писал(а): и хотя бы раз попытаться сделать указатель на функцию с дефолтовым аргументом То есть мало того, что бы удивиться исковерканной логике, надо ещё и закрепить наглядным примером и сверху "камешком придавить" просмотром результата в отладчике! С закреплением на подкорке! Вот только программер,почему-то, всё же от компилятора напоминания в виде ворнинга-таки возжелал... ![]() |
Автор: | Wlad [ Пятница, 06 Март, 2009 01:51 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Alexey Veselovsky писал(а): Код: void foo(A* p_a) {// что-то тут делаем с А} int main() { B* p_b = new B; foo(p_b); } Нет ни малейшего смысла в указателе p_b типа A*. А если так foo(new B); ? ![]() |
Автор: | Alexey Veselovsky [ Пятница, 06 Март, 2009 02:49 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Цитата: Нет ни малейшего смысла в указателе p_b типа A*. А если так foo(new B); ? ![]() Можно и так. Но если использовать после вызова foo объект таки как-то хочется (например уничтожить его), то указатель можно и сохранит. Кстати, проверил, в Аде в точности то же самое с параметрами по умолчанию. Код: package X is type A is tagged null record; procedure foo ( Self : in A; num : Integer := 0); type B is new A with null record; procedure foo (Self: in B; num : Integer := 10); procedure test (some : A'class); end X; Код: with Ada.Text_IO; use Ada.Text_IO; package body X is procedure foo ( Self : in A; num : Integer := 0) is begin Put_Line("A::foo"); Put_Line(Integer'Image(num)); end foo; procedure foo (Self: in B; num : Integer := 10) is begin Put_Line("B::foo"); Put_Line(Integer'Image(num)); end foo; procedure test (some : A'class) is begin foo(some); end test; begin null; end X; Код: with X; procedure Main is B : X.B; A : X.A; begin X.test(B); X.test(A); null; end; вывод программы писал(а): /home/valexey/main
B::foo 0 A::foo 0 |
Автор: | Vlad [ Пятница, 06 Март, 2009 07:49 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Но сам смысл введения наследника от А в виде В подразумевает существования чего-то такого, что или уточняется или отличается в наследниках от того же в предках. Ваши размышления вполне понятны. Но я уверен, что вы поймете и такое размышление. Пользователь класса A, вызывая его метод с дефолтовым параметром, может быть уверен, что в качестве параметра подставится именно то, что он видит в объявлении класса А, а не что-то перекрытое в его наследнике только потому, что функция оказалась виртуальной. А если нужна виртуальность дефолтового параметра, то это делается явно - заводится еще одна виртуальная функция. Лично мне оба этих размышления кажутся равноценными по осмысленности. |
Автор: | Wlad [ Пятница, 06 Март, 2009 10:27 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Vlad писал(а): Ваши размышления вполне понятны. Но я уверен, что вы поймете и такое размышление. Пользователь класса A, вызывая его метод с дефолтовым параметром, может быть уверен, что в качестве параметра подставится именно то, что он видит в объявлении класса А, а не что-то перекрытое в его наследнике только потому, что функция оказалась виртуальной. А если нужна виртуальность дефолтового параметра, то это делается явно - заводится еще одна виртуальная функция. Лично мне оба этих размышления кажутся равноценными по осмысленности. Понимаю. Но принять - решительно отказываюсь.А если я - пользователь класса В и ожидаю, что, не смотря на обобщённый указатель (например в коллекции) у меня наследники будут иметь правильно инициализированные поля класса (которые через параметры по умолчанию получили свои значения)? Вы советуете "завести ещё одну виртуальную функцию?" ОК, посмотрим и на это. Во-первых, я могу не иметь доступа к исходникам класса А. Точка. Во-вторых, для "пользователя класса А", буде появляется параметр по умолчанию, УЖЕ ПРОСТО ПО СМЫСЛУ ВСЁ РАВНО, КАК БУДЕТ ПРОИНИЦИАЛИЗИРОВАН ЭКЗЕМПЛЯР А (ИЛИ ЕГО НАСЛЕДНИК). Собственно для того мы параметр по умолчанию и втулили. А вот пользователю класса В - уже - НЕТ, НЕ ВСЁ РАВНО. Теперь уже смысл факта переопределения умолчания как раз в том, что экземпляры В чем-то и отличаются от экземпляров А (там одно умолчание, здесь - другое - всё ОК - "так задумано")... И - что? Получается, здесь язык ставит препоны для реализации нашего решения о различии? "Пользователи класса А" так и будут работать в терминах и понятиях уровня класса А (более обощённые алгоритмы). А конкретика поведения и наполнения - в наследниках. Но тут мы получили противоречие, исходящее из конкретного свойства языка. Пока, что Ваши доводы меня не убеждают. Может быть Вы, как более плотно работающий с этим, извиняюсь за выражение, языком программирования, укажете (по-конкретнее) на рассуждения автора языка или комитетчиков по поводу обоснования такого поведения? |
Автор: | Wlad [ Пятница, 06 Март, 2009 10:31 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Alexey Veselovsky писал(а): Кстати, проверил, в Аде в точности то же самое с параметрами по умолчанию. Не на гнате, случаем, проверяли?... Ничего противоречивого из того, что там действительно объявлено, с тем, что вызывается и показывается, я лично, не вижу. Что инициализировалось, то и показалось (по типам объявлений и ожидаемым от этого вызовов)... |
Автор: | Alexey Veselovsky [ Пятница, 06 Март, 2009 10:35 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Alexey Veselovsky писал(а): Кстати, проверил, в Аде в точности то же самое с параметрами по умолчанию. Не на гнате, случаем, проверяли?... ![]() На гнате. Гнат полностью соответствует стандарту Ада-95, т.о. это не имеет значения. |
Автор: | Vlad [ Пятница, 06 Март, 2009 16:18 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): Или это так по мозгам трактором логики Си++ проезжаются? Можете называть это "трактором", но "чувствовать" используемый язык - это вполне естественно. Этот пример - хороший вопрос для собеседования, возьму на вооружение. Хороший - не потому что хитрый или с подвохом, а потому что как раз на "чувствование" и потому что есть о чем поговорить независимо от правильности ответа. Владимир Лось писал(а): Vlad, с логикой переназначения виртуальных функций все знакомы. Идя от общего к частному, и считая, что таки описание функции-члена принадлежит конкретному классу, почему вдруг, оказывается, что функция назначается динамикой (по таблице виртуальных методов), а назначение значений по умолчанию в аргументах - по статике? Ну хотя бы потому, что аргументы в C++ всегда статичны и никак не влияют на виртуальность (нет в C++ виртуальности по типу аргумента, например). Единственное исключение тут можно усмотреть в ковариантных виртуальных функциях, и то оно относится к возвращаемому типу, а не к аргументам. Владимир Лось писал(а): Vlad писал(а): P.S. Хотя конечно я бы предпочел, чтобы компилятор ругался в таких случаях (у него для этого все есть). То есть, у вас тоже "червь сомнения есть"У меня нет сомнений в правильности такого дизайна или его какой-то ущербности (на что вы тут делаете упор). Предлагаемый вами дизайн ничуть не лучше (легко представить что и при таком дизайне кто-то мог сильно ругаться). Просто раз ситуация допускает разное толкование, то ее надо избежать. Тем более что это уже сделали для forward declaration обычных функций и шаблонов классов. Владимир Лось писал(а): Vlad писал(а): и хотя бы раз попытаться сделать указатель на функцию с дефолтовым аргументом То есть мало того, что бы удивиться исковерканной логике, надо ещё и закрепить наглядным примером и сверху "камешком придавить" просмотром результата в отладчике! С закреплением на подкорке! Вот только программер,почему-то, всё же от компилятора напоминания в виде ворнинга-таки возжелал... ![]() Отладчик здесь вообще никаким боком. Достаточно понимания, что дефолтовый аргумент никак не влияет на тип указателя на функцию (и никак не участвует при создании экземпляра такого указателя). Если программист на C++ этого не понимает, то у него большой пробел в понимании языка. P.S. Если у вас есть такое сильное желание поглумиться над ущербным дизайном C++ на примере дефолтовых аргументов, то это намного проще сделать без всяких виртуальных функций. file1.cpp: void f(int i) { std::cout << i << std::endl; } file2.cpp: void f(int i = 10); void test1(){ f(); } file3.cpp void f(int i = 20); void test1(); void test2(){ f(); } int main() { test1() test2(); } Здесь даже нарушения ODR нет, если я правильно понимаю. А вот проблема с дизайном языка - налицо. |
Автор: | Vlad [ Пятница, 06 Март, 2009 17:24 ] |
Заголовок сообщения: | Re: ГудвинЪ. Великий и ужасТный! |
Владимир Лось писал(а): А если я - пользователь класса В и ожидаю, что, не смотря на обобщённый указатель (например в коллекции) у меня наследники будут иметь правильно инициализированные поля класса (которые через параметры по умолчанию получили свои значения)? Для инициализации полей класса в C++ принято использовать конструкторы. А вообще в ООП - фабрики. И в конструкторах и в фабриках вы можете использовать параметры по умолчанию ![]() Владимир Лось писал(а): Вы советуете "завести ещё одну виртуальную функцию?" ОК, посмотрим и на это. Во-первых, я могу не иметь доступа к исходникам класса А. Точка. Значит дизайнер класса A не предполагал, что "дефолтовость" будет перегружаться. Мало того, пользователь класса A на такое тоже не расчитывает. Вообще в классе A можно много чего сделать не так и исходников не будет. Например сама функция могла быть невиртуальной. Так что ж теперь, требовать от языка возможности переделать все налету? Ну есть такие языки, у них есть свои проблемы ![]() Владимир Лось писал(а): Во-вторых, для "пользователя класса А", буде появляется параметр по умолчанию, УЖЕ ПРОСТО ПО СМЫСЛУ ВСЁ РАВНО, КАК БУДЕТ ПРОИНИЦИАЛИЗИРОВАН ЭКЗЕМПЛЯР А (ИЛИ ЕГО НАСЛЕДНИК). Собственно для того мы параметр по умолчанию и втулили. А вот пользователю класса В - уже - НЕТ, НЕ ВСЁ РАВНО. Теперь уже смысл факта переопределения умолчания как раз в том, что экземпляры В чем-то и отличаются от экземпляров А (там одно умолчание, здесь - другое - всё ОК - "так задумано")... И - что? Получается, здесь язык ставит препоны для реализации нашего решения о различии? В языке есть базовый механизм переопредения поведения - виртуальные функции. Вы хотите в добавок к этому механизму иметь виртуальность дефолтовых аргументов. Но такого механизма не сделали и по ряду причин. При этом оставили грабли в виде возможности переопределять дефолтовое значение в наследниках. Что вас не устраивает? Грабли сами по себе? Да, меня тоже они не устраивают. Невиртуальность дефолтовых аргументов? Так это легко достигается все через тот же базовый механизм. Владимир Лось писал(а): Пока, что Ваши доводы меня не убеждают. Может быть Вы, как более плотно работающий с этим, извиняюсь за выражение, языком программирования, укажете (по-конкретнее) на рассуждения автора языка или комитетчиков по поводу обоснования такого поведения? Покажите мне язык, где имеется желаемое вами поведение для дефолтовых аргументов (со статической типизацией, естественно). |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |