Предупреждение: управление может достичь конца непустой функции [-Wreturn-type] в боевой функции

Я пытаюсь решить упражнение CodeWars, в котором мне нужно определить победителя между двумя бойцами. Функция возвращает std:string. Проблема, с которой я столкнулся на странице, гласит:

«предупреждение: элемент управления может достичь конца непустой функции [-Wreturn-type] ошибка времени выполнения: выполнение достигло конца функции, возвращающей значение, без возврата значения"

В двух начальных if.

Однако когда я компилирую в своей IDE, такого предупреждения нет. Есть какие-нибудь подсказки о том, что может быть причиной проблемы?

std::string declareWinner(Fighter* fighter1, Fighter* fighter2, std::string firstAttacker) {

    //initialize stats to 0
    int firstAttackerHealth{0}, secondAttackerHealth{0}, secondAttackerDamage{0}, firstAttackerDamage{0};
    std::string secondAttacker;

    //decide who is the first attacker and assign stats values
    if (fighter1->getName() == firstAttacker) {
        firstAttacker =fighter1->getName();
        firstAttackerHealth = fighter1->getHealth();
        firstAttackerDamage = fighter1->getDamagePerAttack();

        secondAttacker = fighter2->getName();
        secondAttackerHealth = fighter2->getHealth();
        secondAttackerDamage = fighter2->getDamagePerAttack();

    }
    else if (fighter2->getName() == firstAttacker) {
        firstAttacker = fighter2->getName();
        firstAttackerHealth = fighter2->getHealth();
        firstAttackerDamage = fighter2->getDamagePerAttack();

        secondAttacker = fighter1->getName();
        secondAttackerHealth = fighter1->getHealth();
        secondAttackerDamage = fighter1->getDamagePerAttack();
    }

    cout << firstAttacker << " vs " << secondAttacker << '\n';
    cout << firstAttacker << " has a total of " << firstAttackerHealth << " points of health   '\n";
    cout << secondAttacker << " has a total of " << secondAttackerHealth << " points of health '\n";
    cout << "Fight!'\n'";

    //start the combat only if both health values are above 0
    while (firstAttackerHealth > 0 && secondAttackerHealth > 0) {

        //check for attacker health, if greater than 0, then they can damage the opponent
        if (firstAttackerHealth > 0) {
            std::cout << firstAttacker << " punches for " << firstAttackerDamage << '\n';
            secondAttackerHealth-=firstAttackerDamage;
            std::cout << secondAttacker << "'s life is now " << secondAttackerHealth << '\n';
        }
        if (secondAttackerHealth > 0) {

            std::cout << secondAttacker << " punches for " << secondAttackerDamage << '\n';
            firstAttackerHealth -= secondAttackerDamage;
            std::cout << firstAttacker << "'s life is now " << firstAttackerHealth << '\n';
        }
            
        // check for the first attacker with health less than 0 and returns the 
        // other attacker
        if (firstAttackerHealth <= 0) {
            std::cout << firstAttacker << "' health is: " << firstAttackerHealth << " , "
                << firstAttacker << " has lost '\n'";
            return secondAttacker;
        }
        else if (secondAttackerHealth <= 0)
        {
            std::cout << secondAttacker << "' health is: " << secondAttackerHealth << " , "
                << secondAttacker << " has lost '\n'";
            return firstAttacker;
        }
    }
}

Поставьте throw 0; в конце функции, и предупреждение будет подавлено.

Eljay 10.04.2024 23:03

Посмотрите пути кода. Внизу вы заканчиваете оператором «иначе, если» и оператором возврата, если это выражение истинно. Если это выражение неверно, вы выпадаете вниз и не существует оператора возврата для выполнения интерфейса метода, который требует возврата строки.

nicomp 10.04.2024 23:04

//начинаем бой, только если оба значения здоровья выше 0. Что произойдет, если это не так. Что возвращается в этом случае?

drescherjm 10.04.2024 23:12

@Ramirojos Кстати, такой оператор if, как if (fighter1->getName() == firstAttacker) { firstAttacker =fighter1->getName();//... не имеет смысла. Причина предупреждения – плохая логика функции.

Vlad from Moscow 10.04.2024 23:21

Если существует вероятность выхода из последнего цикла while (вместо продолжения цикла или выполнения return), это оправдывает предупреждение. Чем сложнее код в цикле, тем сложнее компилятору его проверить, а значит, и вероятность ложного срабатывания. В любом случае добавьте оператор return после цикла - он остановит предупреждение (и предотвратит неопределенное поведение, если цикл когда-либо завершится). И, при необходимости, выполните любые другие проверки (или выдайте предупреждения, или abort(), или что-то еще) в этой точке — если вы считаете, что цикл не завершается, такие тесты выявят любые ошибки.

Peter 11.04.2024 04:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, что компилятор не анализирует код достаточно глубоко, чтобы понять связь между вашим оператором while и if-else-if внизу. Простой способ исправить это — изменить оператор while на

while (true) {

таким образом становится ясно, что из цикла можно выйти только с разрывом или возвратом.

Другая возможность — вынести оператор return за пределы цикла:

    std::string rv;
    while (firstAttackerHealth > 0 && secondAttackerHealth > 0) {

        //check fot attacker health, if greater than 0, then they can damage the opponent
        if (firstAttackerHealth > 0) {
            std::cout << firstAttacker << " punches for " << firstAttackerDamage << '\n';
            secondAttackerHealth-=firstAttackerDamage;
            std::cout << secondAttacker << "'s life is now " << secondAttackerHealth << '\n';
        }
        if (secondAttackerHealth > 0) {

            std::cout << secondAttacker << " punches for " << secondAttackerDamage << '\n';
            firstAttackerHealth -= secondAttackerDamage;
            std::cout << firstAttacker << "'s life is now " << firstAttackerHealth << '\n';
        }
            
        // check for the first attacker with health less than 0 and returns the 
        // other attacker
        if (firstAttackerHealth <= 0) {
            std::cout << firstAttacker << "' health is: " << firstAttackerHealth << " , "
                << firstAttacker << " has lost '\n'";
            rv = secondAttacker;
            break;
        }
        else if (secondAttackerHealth <= 0)
        {
            std::cout << secondAttacker << "' health is: " << secondAttackerHealth << " , "
                << secondAttacker << " has lost '\n'";
            rv = firstAttacker;
            break;
        }
    }
    return rv;

Операторы break на самом деле не нужны, так как условие while в любом случае станет ложным, если часть этого кода будет выполнена.

Второй подход с операторами прерывания очень плох. Вы можете поместить последний оператор if-else вне цикла while.

Vlad from Moscow 10.04.2024 23:23

Другие вопросы по теме