Перегруженная функция, вызванная с одним параметром, но я думал, что передал два

StackOverflow https://stackoverflow.com/questions/2475657

Вопрос

Недавно я рефакторил такой код (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++ без двусмысленностей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top