Обновить

Комментарии 52

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

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

Класс-интерфейс должен иметь только чистые виртуальные функции и не инкапсулировать никакие данные.
НЛО прилетело и опубликовало эту надпись здесь
Вы ко всем моим словам цепляться будете? :)

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

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

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

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

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++ советуют избегать наследования если это возможно, особенно наследования реализации.
Собирался писать статью про наследование и его минусы… С плавным введением в паттерн обертки.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации