Ответы пользователя по тегу C++
  • Почему вылазит link error(не видит вирутальные методы?)?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Потому что шаблон.

    Надо или весь класс определять в хедере, или в array.cpp указывать компилятору генерировать инстанс шаблона с параметром, который нужен в другом cpp файле:
    using Array<int>;

    То же и для очереди.

    Происходит это потому, что компилятор генерирует шаблоны лениво - только когда они нужны. Вот, компилируя array.cpp он не видет вообще ни одного использования шаблона и не генерирует ничего. В каком-нибудь main.cpp у него есть объявление из array.h и использование шаблона. Он и генерирует объявления методов. Но определения-то нигде нет. Оно в array.obj должно быть по вашему замыслу, а там пусто.
    Ответ написан
    1 комментарий
  • Почему выбивает исключение на моменте деления изображения на равные блоки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Наверно, в коде еще есть ошибки, но вот тут:
    vector <double> variances;
    for (int i = 0; i < num_blocks; i++) {
        Scalar mean, stddev;
        meanStdDev(block[i], mean, stddev);
        variances[i] = stddev.val[0];
    }


    Вы записываете в пустой вектор variances по индексу i. Надо или делать push_back в вектор, или выделить его сразу размера num_blocks. Например, так:
    vector <double> variances(num_blocks);

    Еще перепроверьте, что у вас rows/cols не перепутано.
    Ответ написан
    Комментировать
  • Почему не считывает все нажатия вне event loop SFML?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    pollEvent возвращает сообщение из очереди, пока они там есть. В очереди их может оказаться несколько. Именно поэтому там цикл while. А код за циклом обрабатывает только одно - последнее - сообщение. Судя по наблюдаемому вами поведению, в очереди оказывается несколько сообщений.
    Ответ написан
  • Почему не работает GetPixel?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    GetPixel принимает сначала x, потом y. У вас там Height и Width не в том порядке переданы.

    Это будет ошибкой, если одна из сторон более чем в 2 раза больше другой. Это может быть, если у вас широкоформатный монитор.

    У вас там битмап сохраняется в sceen2.png - оно там что-то сохранило вообще? Иначе проблема может быть не GetPixel, а с самим хБитмапом.

    Edit:

    Еще проблема может быть с масштабированием. В результате GetSystemMetrics(SM_CYSCREEN) возвращает не то, что вам надо и BitBlt не срабатывает из-за слишком большого размера.

    Попробуйте вызвать SetProcessDPIAware.

    Еще может быть проблема, что вы SelectObject делаете 2 раза с одним и тем же membit. Надо во второй раз что-то другое подставлять, чтобы HBitmap освободить. Иначе оно, похоже, так и остается привязано к DC.

    Вот мой рабочий код:
    HBITMAP GameManager::GetScreenshot(HWND window) {
    	HDC hScreenDC = GetDC(window);
    	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
    	RECT window_rect;
    	GetClientRect(window, &window_rect);
    	int width = window_rect.right - window_rect.left;
    	int height = window_rect.bottom - window_rect.top; 
    	int result_width = width;
    	int result_height = height;
    	
    	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, result_width, result_height);
    	HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hBitmap));
    	StretchBlt(hMemoryDC, 0, 0, result_width, result_height, hScreenDC, 0, 0, width, height, SRCCOPY);
    	hBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hOldBitmap));
    	DeleteDC(hMemoryDC);
    	DeleteDC(hScreenDC);
    	return hBitmap;
    }
    Ответ написан
    1 комментарий
  • Можно так сделать с interface?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    По уму, вам надо продумать ваш интерфейс. И тогда подобных извращений не понадобится. Дабавьте туда какой-нибудь способ для итерации по структуре данных для вывода. Или вообще сделайте метод ToString, который бы возвращал строковое представление внутренней структуры для вывода. Это все, естественно, виртуальные публичные методы, переопределенные в двух реализациях.

    То же и со вводом. Если надо как-то во внутренности очереди залезать и обычными push это не сделать, то, например, передавайте в метод CreateFromData() вектор введенных пользователем значений.
    Ответ написан
    Комментировать
  • Как сделать какую-нибудь многозадачность на ардуино?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно поменять логику. Включили мотор и постоянно меряете расстояние. Как домеряли до 35см - остановились.

    Можно перед циклом один раз померять - решить, а надо ли вообще мотор включать. Внутри, чтоб электричество зря не жечь, можно даже между вычислениями расстояния сколько-то спать. Смотрите там из расстояния - если оно сильно больше 35 - спите подольше.
    Ответ написан
    2 комментария
  • Почему автодополнение не предлагает мне поля структуры?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы хотите вернуть T. У Node - это член Data. Вот и возвращайте _node->data, или какой там у вас смысл у _node. Пока странно, вы наследуетесь от Array, но никак его не используете. По идее надо возвращать первый элемент в массиве.

    Да, еще, по английски правильно capaCity, а не capaSity.
    Ответ написан
  • Импликация (следование) в C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Нету в C++ отдельных операторов для этих логических функций. Потому что их все можно составить из И, ИЛИ и НЕ.

    Так, импликация - это !a || b. Эквивалентность - можно просто сравнить 2 переменные: a == b.
    Ответ написан
    1 комментарий
  • Как можно перебирать слова в C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Раз у вас во вводе коды каждого символа разделены пробелами, то все просто. Заведите в программе map<wstring, wchar> и где-то в начале напишите 33 строчки вида:
    dict[L"•−"] = L'А';

    Потом входную строку разбейте на части по проблелам. Руками, циклом. Указатель-индекс будет указывать на первый необработанный символ. Найдите первый пробел или конец строки начиная с этой позиции. Кусок между двумя позициями - это текущий код. Его с помощью map'а выше переводите в символ. Сдвигайте индекс первого необработанного символа на позицию после пробела. Ну и аккуратно смотрите, если первый необработанный - пробел, то это пробел между словами - его как есть и выводите, сдвигая индекс необработанного символа на 1.
    Ответ написан
  • Почему не вызывается конструктор копирования при инициализации переменной другим объектом?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Тут сработало copy elision.

    operator& не создает никакого временного Query, а работает сразу с Query в месте его вызова. Поэтому конструктор в пункте 8 создает уже результат.
    Ответ написан
    Комментировать
  • Что делать с этой проблемой?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Исходник в кодировке utf. 'А' действительно занимает 2 байта. Что видит компилятор? Видит 2 байта между кавычками и ругается.

    setlocale() - эта функция во время исполнения программы настроит, в какой кодировке у вас будет просиходить ввод/вывод с консоли. На кодировку исходника оно никак не влияет.

    Тут 2 варианта решения: Или поменяйте кодировку исходника и настройки локали, чтобы 'А' занимало один байт, или работайте с wstring.

    Чтобы не путаться с кодировками, напишите программу, которая выводит численное значение байт прочитанной строки. Запустите ее, введите туда 'А', смотрите, что оно выводит. Поэксперементируйте с разными настройками setlocale(). Если выводит 2 байта - вот эти два байта надо писать в case и использовать wstring. Если выводит один байт, вот его в case и вставляйте.
    Ответ написан
  • Почему выдает ошибку при наследовании?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Для решения этой проблемы по уму надо написать вот это в определении производного класса:
    using Array<T>::_size;
    using Array<T>::_capasity;
    using Array<T>::_data;


    Ответ на вопрос "почему" в С++ всегда один: "потому что стандарт":
    Non-dependent names are looked up and bound at the point of template definition. This binding holds even if at the point of template instantiation there is a better match:


    Проблема в том, что Array зависит от T, а вот его член _size от T не зависит. Ну вот не ищет компилятор независимые имена в зависимых местах. Независимые имена разрешаются в месте определения шаблона, когда еще неясно даже, с каким оно типом будет работать-то. Поэтому он никак до Array достучатся не может, ведь никакого T конкретного у него еще нет.

    Надо как-то компилятору указать, где искать вот эти ваши _size и т.д.
    Например, через this-> или через using или через Array<T>::.

    Вообще от этих правил lookup-а в C++ волосы дыбом встают и куча приколов вылезает. Их надо только запомнить. Оно неинтуитивно, но таково оно есть.
    Ответ написан
    Комментировать
  • Почему внутри шаблона можно иметь доступ к приватному члену внутреннего класса?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    С чего вы взяли, что внутри шаблона это работет? Вы его инстанциировать пробовали (объявить переменную класса Outer<int>, например)?

    Вылезает точно такая же ошибка.

    Если шаблон просто написать, но не использовать его, то он компилироваться и не будет и ошибки в нем не обнаружатся.
    Ответ написан
    1 комментарий
  • Как проверить эфективность линейного и бинарного поиска в простом методе сортировки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Эффективность поиска заключается в количестве срав-
    нений, произведенных определённым методом.


    Ну так подсчитайте количество сравнений. Напишите эти два поиска, заведите счетчики. Во всех местах, где у вас сравнение элементов происходит, увеличивайте счетчик. Выведите их в конце.
    Ответ написан
    Комментировать
  • Почему типы из заголовка cstdint доступны без его включения?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам повезло. Какой-то из включаемых вами других хедеров уже включает cstdint. Поскольку система инклудов в C++ идет еще из C и это дикое и неудобное легаси (текст хедера тупо вставляется в файл вместо include препроцессором), то такое рекурсивное включение работает.

    Но это плохая практика - стоит включать все, что вы используете всегда. Потому что потом вы что-то поменяете, исключив какой-то уже не нужный вам хедер отсюда, или из другого хедера, и у вас вылезет ошибка о неопределенных типах из cstdint.
    Ответ написан
    Комментировать
  • Какую роль играют float и double в скобках?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Такая запись имени типа в скобках в выражении - это явное приведение типа. Тут вы указываете компилятору, что выражение надо преобразовать вот к такому вот типу (флоат, в данном случае).

    float нужен вам в начале, потому что вещественные константы имеют тип double. Поэтому у eps/2.0 и 1.0 в первом цикле имеют тип double, все вычесляется в double. Преобразовав одно из выражений в float вы получаете то, что вам надо. Без этого все вычисления идут в double и ответ находится не тот. На самом деле там float при сравнении все-равно расширяется до double но на результат сравнения это не влияет в данном случае.

    Еще, вместо явного приведения типов, можно поставить f после вещественных констант, чтобы указать компилятору, что это float:
    while (1 + eps/2.0f != 1.0f){

    Тогда вычисления будут во float и ответ будет правильный.

    Во втором цикле double вам не нужен. Ведь вычисления итак идут в этом типе. Да и написано у вас там с опечаткой, вы к типу double приводите все выражение со сравнением. т.е. вы булево значение преобразуете в дабл. Потом оно назад в булево преобразуется при проверке условия циклом. В итоге это бесполезное действие.
    Ответ написан
    Комментировать
  • Крестики-нолики.Проблемы с ходом Х?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    У вас там бесконечный цикл, который читает ход Х. Без единого break внутри - поэтому нет даже теоретической возможности, что вы из него выйдите.

    Упростите код: эти 9 if else условий заменяются на такой код:
    if (us.length() != 2) {
      cout << "?????" << endl;
      continue;
    }
    int row = us[0]-'A';
    int col = us[1]-'0';
    if (row < 0 || row > 2 || col < 0 || col > 2) {
      cout << "????" << endl;
      continue;
    }
    if (pole[row][col] != '_') {
      cout  << "занято" << endl;
      continue;
    }
    pole[row][col] = 'X';
    break;
    Ответ написан
    Комментировать
  • Может ли прерывание прервать выполнение конструктора / деструктора в С++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Да, может. Но обычно в самих конструкторах о многопоточном доступе не беспокоятся, потому что пока конструктор выполняется - объекта еще нет и никакой конкурентный доступ к нему невозможен. Если конструктор обращается к каким-то другим ресурсам, то вот те ресурсы должны защищаться от многопоточных проблем как обычно - не важно из конструктора к ним обращаются или из какого-то другого метода какого-то класса.
    Ответ написан
    Комментировать
  • Как запретить std:: vector перемещаться?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно через vector::reserve задать ему необходимый объем. Тогда он сразу же выделит все память и, если вы не будете в него класть больше этого размера элементы, он не будет перевыделять память вообще.

    Еще можно изменить ваш дизайн. Например, вместо vector использовать list, итераторы в котором не портятся от добавления. Или хранить вместо итераторов/указателей на элементы в векторе индексы.
    Ответ написан
    Комментировать
  • Можно в c++ ли работать с памятью через stream?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Класс std::stringstream как раз это и реализует.
    #include <stringstream>
    
    std::stringstream sout;
    sout << "some string " << 42;
    cout << sout.str();


    Но для сериализации эффективнее будет руками записывать данные в буфер через memcopy: все члены структуры по отдельности чтобы не было проблем с выравниванием. Для строк переменной длины надо будет писать еще и их размер отдельно. Для чисел надо аккуратно с порядком байт разобраться и писать их побайтово.
    Ответ написан
    Комментировать