Задать вопрос
  • Где лучше включать заголовочные файлы?

    Nipheris
    @Nipheris Куратор тега C++
    Даниил Демидко
    > а инклуд определения класса делать там, где без него уже никак - например там, где вызываются методы класса или создаются его экземпляры.

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

    Поймите, по сути разбиение на h/cpp это такой хак, необходимый из-за отсутствия (пока что) модульности в C++. Из-за того, что компилятор не умеет собирать информацию по нескольким файлам исходников (как в других языках), при компиляции конкретного cpp компилятору нужна ВСЯ необходимая информация для обработки исходного кода в этом cpp. Наличие этой информации достигается использованием инклудов - вы как бы просите препроцессор собрать для компилятора всю нужную информацию в один файл (который кстати будет намного толще в случае большой иерархии хедеров). Это и определения классов, и typedef-ы, и реализации ШАБЛОННЫХ методов и функций и т.д. После этого компилятор прочтет все нужные определения и сможет ими воспользоваться в нужных местах при обработке кода, находящегося в исходном cpp.
    Однако, т.к. конечный бинарник будет линковаться линкером, то при компиляции отдельной "единицы компиляции" (т.е. нашего cpp) нет необходимости иметь определения обыкновенных (нешаблонных) функций и методов - ссылки на них будет ставить уже линковщик. Поэтому правило простое - все МАКСИМАЛЬНО выносится в "единицу компиляции", а та информация, без которой невозможно собирать остальной зависимый код - в хедер. Поэтому, например, реализации методов класса - в cpp, а определение самого класса - в хедере.
    Из-за этого кстати появляются различные проблемы, например недостаточная абстракция реализации класса от интерфейса - т.к. экземпляры класса создаются не опосредованно через фабрики, а непосредственно по их определению в месте использования new, то при изменении определения класса (например, добавлении поля или изменении его типа) требуется перекомпиляция всего зависимого кода, т.к. может измениться размер объекта, и вообще нарушиться бинарная совместимость (т.е. DLL-ку/SO-шку уже просто так не поменяешь). Для решения этой проблемы используется, например, упомянутый Vitaly pImpl (там, где бинарную совместимость очень уж хочется). Есть и другие способы, например создание вынесение публичного интерфейса и создание пар функций-фабрик (create/destroy), чтобы переместить код создания/удаления внутрь нужного бинарника.
  • Какие правила прописать на OpenVPN сервере, чтобы через него шёл интернет к клиенту?

    > Пробовал всякие разные комбинации команд iptables из мануалов с просторов интернета, но результат одинаковый - интернета на клиенте нет.
    Какие конкретно? NAT в тех комбинациях был?
  • Как вычислить значение функции, заданной в виде строки?

    Nipheris
    @Nipheris Куратор тега C#
    Синтаксис этой строки уточните пожалуйста.
  • Как делать красивые окна в C#, упростить разработку и усложнить компиляцию и реверсинг?

    Nipheris
    @Nipheris Куратор тега C#
    Жесть, до чего техника дошла. Десктопные приложения теперь хотят делать "как в html чтоб менюшки были", а каких-то лет 7 назад все было наоборот.
  • Инкапсуляция, отсутствие её - проблема?

    bromzh Вообще, инкапсуляция с точки зрения состояния объекта - это выпиливание "некорректных" состояний из множества состояний, являющегося декартовым произведением состояний частей объекта. Делая все или часть полей приватными, а методы с нужной логикой - публичными, мы тем самым не позволяем объекту перейти в некорректное с нашей точки зрения состояние. В этом собственно и отличие объекта от кортежа/записи, в которой значение каждого компонента можно задать независимо от других.
    Поэтому, и public и protected методы должны в равной степени заботиться о состоянии объекта, а методы, переопределенные в наследниках - заботиться о том, чтобы сохранялись все поведенческие черты родительского метода. Интерфейс метода - это НЕ ТОЛЬКО его параметры и возвращаемое значение. Это еще и все то, что клиентский код ожидает от класса, что описывается в документации и согласуется с общей логикой класса (это к примеру о методе add).
  • Инкапсуляция, отсутствие её - проблема?

    bromzh
    > Тот, кто использует библиотеку вполне может получить "приватный" член класса. Но это как бы будут его проблемы.
    Вот очень правильно вы написали, что если человек обращается к "приватному" члену, то это его проблемы. Только об этом ему будет в каждой строке кода кричать нижнее подчеркивание. В любой момент достаточно глянуть на код и будет видно, что некоторые соглашения нарушаются.
    А вот когда я смотрю на API, я думаю о нем как об API. Т.е. как о некотором контракте, который мы оба - я, пользователь либы, и ее разработчик - должны соблюдать. И обычно люди рассчитывают на то, что этот контракт был предварительно обдуман. Более того, если либа следует semantic versioning, это накладывает доп. ограничения на свободу модификации API и требует корректной смены версий. И получается, я должен как-то догадаться, что разработчик НЕ соблюдает все эти негласные правила? Даже, если я догадаюсь, то тогда мне нужно читать код либы, чтобы разобраться. А либа, чей куда нужно читать для ее использования, по сути не нужна, т.к. не решает за меня нужную мне подзадачу (я частично превращаюсь в ее разработчика).

    Пару слов о protected. В принципе можно довольно долго рассуждать, реально ли необходима protected область видимости или же это излишнее усложнение, но раз мы взялись говорить о языках, где такой модификатор наличествует, то мне кажется вы совершенно не представляете, как им пользоваться.
    > Мы можем изменить эти реализации и сломать работу дочернего класса.
    Точно также я могу изменить реализации публичных методов, и сломать работу клиентов класса. protected-члены это тоже интерфейс, и к нему тоже нужно подходить ответственно. Конечно, он подразумевает более плотное взаимодействие, чем public, и как правило иерархия классов не выходит за пределы подсистемы/библиотеки/модуля, но тем не менее для protected методов точно также нужно соблюдать пред- и постусловия, как и для public. Да, эти условия невозможно задавать в рамках рассматриваемых языков, чтобы их проверял компилятор, но нарушает ли это инкапсуляцию? Ведь в Питоне интерпретатор тоже не бьет по рукам за обращение к "приватным" членам, т.к. это всего лишь договоренность.
    В последнем примере например нарушены постусловия для переопределенного add: разумеется, пользователь класса ожидает, что add добавит элемент ОДИН раз и количество элементов множества увеличится НА 1. Собственно, проваленный тест в каком-то смысле и есть задокументированное постусловие, которое было нарушено.
    А вообще, "inheritance CAN break encapsulation" != "inheritance break encapsulation". Вы или забыли это упомянуть в ответе, либо предпочли не знакомиться с деталями проблемы.

    > Как вариант, можно общую логику реализовывать в абстрактных классах, а в их наследниках реализовывать только абстрактные методы родителя.
    Да, вот именно такой вариант часто и используют, делая protected virtual функции, позволяя переопределить только некоторые фрагменты логики, вынося общее в родителя.
  • Инкапсуляция, отсутствие её - проблема?

    > Просто ответственность за правильное использование апи перекладывается с разработчика апи на разработчика, использующего это апи.
    Если уж это не проблема, то тогда что вообще можно назвать проблемой?)

    > Ну и к слову: наследование классов нарушает инкапсуляцию (для protected-полей и методов).
    м, каким образом?
  • Windows Installer XML. Как сделать окно, в котором я укажу название БД, параметры подключения, чтобы потом выполнить скрипт и создать БД?

    Nipheris
    @Nipheris Куратор тега C#
    Пишите на мыло в профиле, на выходных могу глянуть, если "поджимает" это не "сегодня к 5-ти вечера"
  • Проблемы с VS 2015. Как заставить работать C#?

    Nipheris
    @Nipheris Куратор тега C#
    5oundtech обе команды успешно выполнились или какие-то ошибки были?
  • Чем отличаются языки программирования PHP, PYTHON, RUBY?

    RU проверьте, правильно ли вы выбрали адресата для комментария :)
  • ADO.NET море проблем?

    Nipheris
    @Nipheris Куратор тега C#
    Какая редакция студии?
  • Чем отличаются языки программирования PHP, PYTHON, RUBY?

    zugo
    качество кода на нем зависит исключительно от квалификации кодера, а не от того, что язык, якобы, плохой
    качество кода на большинстве достаточно мощных и гибких языков зависит прежде всего от квалификации программиста. Вопрос прежде всего в том, насколько плохо язык позволяет писать код. Я считаю, что слабая типизация это угар, особенно для новичка (джаваскрипт кстати туда же). Операторов сравнения по две штуки, внезапные касты, совсем зеленые люди вообще не могут отличить 1 от "1". Так что правильно упомянутые вами "пхп-макаки" отмазываются - для НИХ этот язык и правда плохой.
    Да, есть еще всякие мелочи вроде '<?php' в начале скрипта и тот факт, что конструкцию func()[index] стало можно использовать не так давно. Сами по себе они несущественны, но о дизайне языка в целом они говорят хорошо.
    И раздувающимся от самомнения "ынтырпрайз-сеньера", дескать, мы-то на настоящем языке пишем, а не на пыхопе каком-то
    Какие-то у вас неправильные интерпрайз-сеньоры. Нормальные интерпрайз-сеньоры раздуваются от того, что имеют дело со всякими WS-Trust, SAML и прочими Service Bus-ами и SOAPами, а не от того, что они выучили язык и пишут на нем. И платят им больше, потому что они работают в банках и страховых, и пишут софт, чтобы деньгу гонять туда-сюда. А почему так произошло, я в 1-м пункте ответа написал.

    Да, кстати, а где же "ворох стереотипов"? Вам кроме PHP есть что прокомментировать?
  • Аналог QStringBuilder для ванильного с++. Где взять?

    Nipheris
    @Nipheris Куратор тега C++
    @Taraflex

    template 
    std::stringstream& operator%(std::stringstream& left, T right) {
    	left << right;
    	return left;
    }
    
    int main() {
    	std::stringstream out;
    	std::string val = "hello world";
    	int p = 100500;
    	out % '[' % val % " : " %  p % ']';
    	std::cout << out.str();
    	return 0;
    }


    Улучшить-то можно много чего, например чтобы implicit-каст к строке был, но.. зачем? Чем же вам оператор сдвига не угодил? У него ж как раз приоритет низкий, очень удобно пользоваться. Если уж вы "ванильный" вариант спрашиваете, то юзайте и "ванильный" стиль написания. Или перепишите QStringBuilder для стандартных строк, если уж вы заморочены на приятном синтаксисе.
  • Где точнее буду производится математические операции с плавающей запятой на Java или на C++?

    Nipheris
    @Nipheris Куратор тега C++
    Кстати, в спецификации Java https://docs.oracle.com/javase/specs/jls/se8/jls8.pdf указано, что float и double работают по стандарту ANSI/IEEE Standard 754-1985. Аналогично можно узнать и для C++ для конкретного компилятора.