Pull to refresh

Comments 52

Почему блок cop, если больше половины вопросов это просто понимание ООП пкрадигмы.и знания шаблонов проектирования?
Потому что не зная C++ не ответить на другую половину вопросов?
Часть вопросов завязаны на C++. Эти вопросы представляют для меня определённую ценность. Не мог их исключить. С другой стороны программист на C# и Java никогда не расскажет про виртуальный деструктор…
Вы еще вспомните программистов 1С :)
Я себя никак сишником не считаю, но про деструкторы помню из прочитанной для общего развития книги.
Я это к чему — на первый взгляд опрос очень общий, но может это я придираюсь так полуночно.
Это вопрос на особенность реализации ООП в конкретном языке… Потому опрос в блоге C++. Если бы опуюликовал в блоге «ПРограммирование» — огрёб бы там от шарпистов, питонистов, яверов и прочих уважаемых девелоперов)
Программист Java, но зачем в C++ — языке без интерфейсов, сборщике мусора и с множественным наследованием — виртуальные деструкторы — догадался.
Чем реализация интерфейса качественно отличается от наследования от абстрактного класса?
В случае с С++ только добросовестностью программиста :)
UFO just landed and posted this here
Но качественное отличие, не реализуемое языком C++, абстрактного класса от интерфейса не в том же, кто может быть создан, а кто нет. Класс реализующий интерфейс ДОЛЖЕН реализовать все его методы, а вот класс наследующийся от абстрактного класса может оставаться абстрактным.

Ну по-крайней мере я так это всегда понимал :)
UFO just landed and posted this here
Это из принципов ООП :) Почему только Ява? А тот же СиШарп?

Класс-интерфейс должен иметь только чистые виртуальные функции и не инкапсулировать никакие данные.
UFO just landed and posted this here
Вы ко всем моим словам цепляться будете? :)

Нет, интерфейс — это точно не сущность, это контракт, протокол — нечто вроде соглашения, которое гласит — класс, реализующий этот интерфейс — обязательно будет реализовать «вот такое вот» поведение. У интерфейса могут быть свойства, но только в виде аксессоров. Т.е. они опять же, не могут хранить данные, а только определяют поведение класса, реализующего интерфейс.

Как-то так.
UFO just landed and posted this here
Если бы меня попросили дать определение интерфейсу…
Каждый экземпляр класса имеет интерфейс и данные (приватные методы нас не интересуют, так как бесполезны для стороннего наблюдателя). Для обобщения группы классов используют механизм выделения и явного описания интерфейса. Он выражен программной сущностью в Java, C# — interface, Objective-C — protocol, C++ — class с некоторыми «особенностями». Интерфейс не должен содержать ничего помимо чисто виртуальных публичных методов. В интерфейсе на языке C++ должен содержаться виртуальный деструктор. По сути интерфейс является программной сущностью, позволяющей унифицировать неявные интерфейсы классов в явный.
UFO just landed and posted this here
UFO just landed and posted this here
Интерфейсы нужны. Смартпоинтеры необходимы. А если еще и ООП правильно применять — то понижается сложность ПО!!! Это ведь главная задача ООП. Без интерфейсов ООП не ООП, а говнокод.
UFO just landed and posted this here
Если часть кода программы располагается в EXE, а другая в DLL — то при инклюде абстрактного класса его код будет скомпилирован дважды и будет присутствовать и в EXE и в DLL. Это может повлечь определенные проблемы…

Про смартпоинтеры я написал в ответ на GC. У смартпоинтеров в C++ нет таких проблем с освобождением ресурсов, как в C#. Это там где юзинг используют…
UFO just landed and posted this here
Проблема существует. Скажем так, вы пока с ней не сталкивались. Для меня всё GC, где не надо делать delete, остальное уже детали… Сразу он удаляет или переодично… Сути не меняет. Кстати, проблема актуальна с STL-объектами, передаваемыми из/в DLL… Ни разу std::string в функцию из DLL не передавали параметром?
UFO just landed and posted this here
То есть CPP использовать в разных модулях это серьёзная ошибка, а абстрактные классы — не ошибка? В них же тоже есть исполняемый код… Такая же ошибка. Интерфейс тем крут, что в нем нет исполняемого кода, и его можно использовать в любых проектах без проблем…
UFO just landed and posted this here
А как насчёт сложности использования абстрактных классов. Нужно будет смотреть что в нем реализовано, что можно использовать наследником и т.д. Тут как бы трабл с инкапсуляцией. Да и вообще помнить то как устроен абстрактный класс — накладно! Чем меньше связность — тем проще кодить. Последние 2 года использую принципы ООП и повсюду где применимо описываю интерфейсы — так вот больше нет неприятных моментов, когда код проекта замесился в лапшу непонятную и непонятно что куда дописывать и для новой фичи программы надо половину кода перелопатить… Каждая новая фича — отдельный класс который потом всего в 1 месте подключаю к программе… Использование абстрактных классов заставит вас запоминать больше, а это основная проблема программирования…
У меня есть одна мысль насчёт голосования. Вопрос сформулирован таким образом, что проценты считаются неверно… В пером пункте поставили галочку 23 человека из 97 — это 23.71%, а не 6.02%. Проценты надо считать относительно голосовавших людей, а не общего числа галочек всех голосовавших…

Пожалуй напишу в саппорт петицию о настраивании порядка вычисления процентов…
Я конечно знал, что программист я фиговый, но чтобы ни на один вопрос не ответить…
UFO just landed and posted this here
Общее/частное, часть/целое, качественные отличия — это понятия скорее из диалектики, а не из программирования. Я бы на них ответил не однозначно, но всё же уверенно.
А вы сможете ответить?

1. Чем отличаются const-методы от прочих?
2. Какой смысл в константной передаче параметров по ссылке (const SomeTypeName &variable)?
3. Что такое список инициализации конструктора?
4. Что делает (или чего не делает) конструктор со служебным словом explicit?
5. Что такое KISS?
6. Какие бывают умные указатели?

Я могу придумать еще с десяток вопросов. И точно также я могу задать эти вопросы Гуглю. А еще есть матрица компетентности программиста. Но единственным мерилом как был, так и остается написанный вами код.
1. Не должны менять состояние класса (исключение — mutable)
2. Смысл в том, что и объект если надо сконструируется и изменить не даст существующий объект
3. Это для инициализаии полей, важно что порядок инициализации не зависит от порядка указания в списке инициализации, а зависит лишь от порядка полей в классе.
4. Не даёт сконструировать объект из параметра автоматом. Например, у всех смартпоинтеров приходится писать func(ShapePtr(shape)); вместо func(shape);
5. Впервые слышу
6. Интруизивные, невладеющие, «массивные»))
Это хорошо. :)

1. Точно так. Неизменяемые методы дают гарантию, что класс останется нетронутым, что не будет побочных эффектов.
2. Так, да не совсем. Главный смысл — избежать оверхеда в копировании больших объектов и при этом оставить синтаксис вызова удобным. Ведь можно было бы передавать по константному указателю (допустим, огромную строку), но тогда бы пришлось как снаружи писать амперсанд, так и внутри обращаться к указателю через стрелку. Но если использовать передачу по неконстантной ссылке, не было бы гарантии, что объект внутри метода не изменится. Поэтому — константная ссылка. Ничего не создается.
3. Верно!
4. Тоже верно, буквально — запрещает автоприведение типов.
5. Keep It Simple, Stupid! Он же «Бритва Оккама». (А еще есть интересная аббревиатура YAGNI — «вам это не понадобится» — то есть, не делать лишнего, пока действительно не припечет.)
6. Да, их много.
На самом деле explicit в конструкторах смартпоинтеров жутко бесит. Возможно он защищает меня от самого себя, но жуть как неудобно. Даже функцию написал типа:
template<typename T>
std::tr1::shared_ptr<T> Shared(T * t)
{
    return std::tr1::shared_ptr<T>(t);
}

Теперь в коде если explicit мешает пишу просто Shared(указатель)…
В таком случае можно попробовать не использовать умные указатели. Но требуется несколько иной подход к разработке. Центральным постулатом этого подхода является принцип «Выделение памяти — это инициализация». При нем следует не использовать new/delete (как следствие — указатели обычные и умные), а создавать экземпляры статически (Object obj = Object();). Однако иногда требуется хранить указатели на эти объекты, — и тут могут возникнуть проблемы с STL-контейнерами (кажется, там указатели могут быть удалены в некотором случае). Тут, конечно, и умные указатели в помощь.
Тогда придется возиться с взятием адреса для полиморфизма…
Да уж… Код — он вообще такой. С ним все равно нужно возиться, — какой бы подход ни был. И тут вступает в действие очередной принцип: «Пиши код, ...!». Просто иначе — никак.
Мда :) Ваш весьма пространный ответ на второй вопрос и не знание аббревиатуры KISS родил у меня в голове негодование «И вот этот человек, спрашивает, что такое SOLID?»
Скажу так, то что через стек будет передана ссылка на объект я считал просто очевидным. Это же ссылка, иначе и быть не может! Я имел виду вот какую особенность:
void func(const std::string & str);

std::string str = "xyz";
func("abc"); // Есть конструирование объекта
func(str); // Нет копирования объекта


Насчет KISS — возможно слышал когда-то… Что не впечатлило.
Да я верю, что Вы знаете про константные ссылки, это я уж так, к слову сказал :)

Я когда увидел голосование, подумал, что захотели проверить, все ли прочитали Вашу статью про ООП? :)
>>Чем представлено отношение общее/частное в исходном коде?
Как вообще понять этот вопрос?
Кем представлено и в каком таком коде?
Если конкретизировать, то какой синтаксической конструкцией на языке программирования высокого уровня представляется отношение общее/частное между программными сущностями? Нужно значть это за отношение… Что соотносится друг с другом, как уточнение чего-то обобщённого?
Изначальный вопрос построен неверно, и по этому я не могу ответить на такой вопрос.
Если бы было написано «Чем может быть представлено отношение общее/частное», «Чем представляется отношение общее/частное» или «Как можно представить отношение общее/частное» то вопросов бы не возникало.
Кстати, отношение общее/частное не обязательно выражать наследованием, см. тот-же COM к примеру.
Вы уж извините, это больше похоже на придирку. Похоже вы можете дать развернутый ответ на вопрос и даже поспорить о тонкостях русского языка. Суть вопроса и была выявить, в состоянии вы это обсудить или нет. Не сумев ответить на некорректный с вашей точки зрения вопрос вы тем самым на него ответили в тот момент, когда стали рассуждать об его правильности. И не могли бы вы пояснить про COM?
Интерфейсы общего и частного в COM не обязательно должны быть связанны наследованием, они обязаны наследоваться только от IUnknown и могут быть не связанными друг с другом.
При этом, имея указатель на один из интерфейсов, можно запросить второй интерфейс при помощи вызова QueryInterface.
Более того — наследование интерфейсов COM друг от друга во многих случаях даже мешает.
К примеру может возникнуть проблема ромбовидного наследования при реализации этих интерфейсов.

Это я к тому, что при проектировании своей архитектуры не нужно принимать за правило то, что «если есть связь общее/целое то нам необходимо применять наследование».

Во многих книжках по C++ советуют избегать наследования если это возможно, особенно наследования реализации.
Собирался писать статью про наследование и его минусы… С плавным введением в паттерн обертки.
А ничего, что C++ не поддерживает интерфейсы в принципе? Подобное ключевое слово отсутствует как факт. Заместо интерфейсов используются чисто абстрактные базовые классы. Впрочем это не совсем интерфейс. Ведь при ромбовидном наследовании возникнут артефакты, нет?
Лучше тогда про виртуальное наследование вопрос задать!
UFO just landed and posted this here
Sign up to leave a comment.

Articles