Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Непонятное использование оператора double()

Автор вопроса: Alex GoftОтветов: 3

У меня есть класс Rectangle с операторами преобразования как в double, так и в std::string:

class Rectangle
{
public:
    Rectangle(double x, double y) : _x(x), _y(y) {}
    operator std::string ();
    operator double ();
private:
    double _x, _y;
    double getArea() {return _x * _y;}
};

int main()
{
    Rectangle r(3, 2.5);
    cout << r << endl;
    return 0;
}

Я не понимаю, почему вызывается operator double(), а не operator std::string(). Насколько мне известно, согласно викибуку по C++, operator double является используется для преобразования Rectangle объектов в double.

Так что же здесь происходит? Связано ли это с тем, что конструктору передается int? Если да, то почему?

  • Что вообще означает преобразование прямоугольника в двойное. 16.09.2015
  • я думаю (двойной) г или что-то Alex Goft 16.09.2015
  • @AlexGoft Нет, другой Алекс имел в виду "что это значит логически?". Со стороны операция кажется бессмысленной. Konrad Rudolph 16.09.2015
  • Я подозреваю, что он имел в виду область, поскольку нет другой причины включать функцию getArea() в образец. Zac Crites 16.09.2015

c++operator-overloadingimplicit-conversion

Ответы

Ответ 1 · рейтинг 13 · NathanOliver

У вас нет оператора для вывода прямоугольника в поток. cout имеет перегрузку, которая принимает double, и ваш класс может быть неявно преобразован в double, поэтому он выбран.

Причина, по которой перегрузка строки не выбрана и не рассматривается как двусмысленность, заключается в том, что operator << для строки является функцией-членом и не включена в перегрузка члена и перегрузка, не являющаяся членом набор из cout. Если мы закомментируем operator double, мы увидим, что мы получаем ошибку компиляции.

Если мы хотим вызвать operator string, нам нужно будет явно привести r к строке. Живой пример

Ответ 2 · рейтинг 6 · Oktalist

Поскольку вы не предоставили перегрузку operator<< для Rectangle, компилятор рассматривает другие перегрузки, для которых аргументы могут быть преобразованы в типы параметров.

Если какая-либо из перегрузок является шаблоном, то подстановка аргумента шаблона происходит с ними до разрешения перегрузки. Компилятор пытается вывести параметры шаблона из типов аргументов, переданных функции.

Перегрузка string не рассматривается из-за ошибки подстановки аргумента шаблона:

template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os,
               const std::basic_string<CharT, Traits, Allocator>& str);

Подстановка аргументов шаблона не учитывает пользовательские преобразования, поэтому компилятор не может вывести типы CharT, Traits или Allocator из типа Rectangle, поэтому эта перегрузка не участвует в разрешении перегрузки. (Напомним, что std::string - это просто определение типа std::basic_string<char, std::char_traits<char>, std::allocator<char>>.)

Следовательно, есть одна перегрузка operator<<, которая лучше подходит, чем любая другая, и это перегрузка double. Не шаблон, а функция-член шаблона класса.

basic_ostream<CharT, Traits>& basic_ostream<CharT, Traits>::operator<<(double);

Ответ 3 · AmirArbel

В двойной перегрузке нет ничего особенного, кроме перегрузок других примитивных типов. В данном случае это единственная доступная примитивная перегрузка. Компилятор будет вести себя одинаково для int, char и т. д.

Обратите внимание, что если у нас будет более одной перегрузки примитивного типа, компилятор выдаст

error: ambiguous overload for 'operator<<' ...

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы