Я пытаюсь решить упражнение 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;
}
}
}
Посмотрите пути кода. Внизу вы заканчиваете оператором «иначе, если» и оператором возврата, если это выражение истинно. Если это выражение неверно, вы выпадаете вниз и не существует оператора возврата для выполнения интерфейса метода, который требует возврата строки.
//начинаем бой, только если оба значения здоровья выше 0. Что произойдет, если это не так. Что возвращается в этом случае?
@Ramirojos Кстати, такой оператор if, как if (fighter1->getName() == firstAttacker) { firstAttacker =fighter1->getName();//... не имеет смысла. Причина предупреждения – плохая логика функции.
Если существует вероятность выхода из последнего цикла while
(вместо продолжения цикла или выполнения return
), это оправдывает предупреждение. Чем сложнее код в цикле, тем сложнее компилятору его проверить, а значит, и вероятность ложного срабатывания. В любом случае добавьте оператор return после цикла - он остановит предупреждение (и предотвратит неопределенное поведение, если цикл когда-либо завершится). И, при необходимости, выполните любые другие проверки (или выдайте предупреждения, или abort()
, или что-то еще) в этой точке — если вы считаете, что цикл не завершается, такие тесты выявят любые ошибки.
Проблема в том, что компилятор не анализирует код достаточно глубоко, чтобы понять связь между вашим оператором 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.
Поставьте
throw 0;
в конце функции, и предупреждение будет подавлено.