Перегруженная функция, вызванная с одним параметром, но я думал, что передал два
-
21-09-2019 - |
Вопрос
Недавно я рефакторил такой код (MyClass
к MyClassR
).
#include <iostream>
class SomeMember
{
public:
double m_value;
SomeMember() : m_value(0) {}
SomeMember(int a) : m_value(a) {}
SomeMember(int a, int b)
: m_value(static_cast<double>(a) / 3.14159 +
static_cast<double>(b) / 2.71828)
{}
};
class MyClass
{
public:
SomeMember m_first, m_second, m_third;
MyClass(const bool isUp, const int x, const int y)
{
if (isUp)
{
m_first = SomeMember(x);
m_second = SomeMember(y);
m_third = SomeMember(x, y);
}
else
{
m_first = SomeMember(y);
m_second = SomeMember(x);
m_third = SomeMember(y, x);
}
}
};
class MyClassR
{
public:
SomeMember m_first, m_second, m_third;
MyClassR(const bool isUp, const int x, const int y)
: m_first(isUp ? x : y)
, m_second(isUp ? y : x)
, m_third(isUp ? x, y : y, x)
{
}
};
int main()
{
MyClass a(true, 1, 2);
MyClassR b(true, 1, 2);
using namespace std;
cout.precision(10);
cout
<< "a:" << endl
<< "\tfirst: " << a.m_first.m_value
<< "\tsecond: " << a.m_second.m_value
<< "\tthird: " << a.m_third.m_value << endl;
cout
<< "b:" << endl
<< "\tfirst: " << b.m_first.m_value
<< "\tsecond: " << b.m_second.m_value
<< "\tthird: " << b.m_third.m_value << endl;
return 0;
}
- В чем ошибка,
- почему он компилируется (проверено с VC6 а также предупреждение VC9 уровня 4:претензий нет) и
- как правильно это сделать?
Я (предполагаю) у меня уже есть все эти ответы, но я думаю, что это интересная проблема, которой стоит поделиться.
Обновлять
Расширенный код, позволяющий «копировать, вставлять и выполнять».VC9 тоже не предъявил мне никаких претензий. VC6 здесь не проблема.
Для полноты вывода:
a:
first: 1 second: 2 third: 1.054069532
b:
first: 1 second: 2 third: 1.004499999
Решение
Я не уверен, чего именно вы ожидаете, но давайте начнем…
Прежде всего, откажитесь от VC6. Серьезно. Его использование — огромная проблема, поскольку оно не соответствует стандартам и исключает множество вариантов.Правильное его использование похоже на игру в русскую рулетку.
Ваш конструктор
m_third
не делает того, что вы думаете.Вы не можете написать условное выражение, подобное этому:«несколько параметров» не является допустимым выражение в C++, а условный оператор работает с выражениями.Код компилируется, потому что он все еще правильный, он просто не делает то, что вы хотите.Вместо использования «нескольких параметров» он оценивает оператор точки последовательности (
,
), который просто принимает последний значение выражения, поэтому ваше условие фактически эквивалентно:isUp ? y : x
Правильный способ — использовать два условные обозначения:
m_third(isUp ? x : y, isUp ? y : x)
Третий конструктор
SomeMember
неверно, значение может переполниться, что приведет к отрицательному значению — я очень сомневаюсь, что это то, что вам нужно.
Другие советы
m_third(isUp ? x, y : y, x)
Это выглядит неправильно.Первый x
является бессмысленным выражением, поскольку оно не имеет побочных эффектов и результат не используется, тогда две стороны :
имеют одинаковую ценность и побочные эффекты, поэтому ?:
можно исключить как выражение перед ?
также не имеет побочных эффектов.
m_third(y, x)
Но теперь он не делает то, что делает исходный код...это ошибка?
Какая ошибка, что такое правильный способ сделать это?
Полагаю, вы намерены показать какое-то наивное использование оператора-запятой в сочетании с троичным ?, возможно, здесь скрыта какая-то умная и неожиданная ошибка с приоритетом оператора, но я думаю, что код абсолютно искусственный.Если это так, то я бы сказал, что «правильный способ сделать это» - не использовать C++ или сначала изучить его, прежде чем использовать.Да, в нем есть много конструкций, которые могут выглядеть как «причуды», и вы можете создать много странно выглядящего кода, принимаемого компилятором.Я бы сказал, что, используя C++, вы должны знать эти инструменты.
Почему компилируется
Потому что он не содержит ошибок и представляет собой правильный код C++ без двусмысленностей.