Разница между `cout << x` и` cout.operator << (x) `и` оператором (std :: cout, x) `?

0

Это связано с вопросом разницы между cout-x-и-cout-operator-x, но все же немного отличается...

#include <iostream>

int main(){
    std::cout << "hello" << std::endl;

    std::cout.operator<<("hello2");
    std::cout.operator<<(std::endl);

    operator<<(std::cout, "hello3");
//    operator<<(std::cout, std::endl);

    return 0;
}

Q1: Почему std::cout.operator<<("hello2"); Работа?

Из других ответов на SO я ожидал бы, что компилятор будет жаловаться, поскольку operator<< означает свободную функцию, а не член cout. Однако в моей системе он печатает "0x10d54df31". И, еще более странно, следующая строка правильно корректно выполняет std::endl.

Q2: Почему operator<<(std::cout, std::endl); не работа?

Я знаю, что std::endl - это функция, но мне кажется странным, что выход hello3 работает, а "std :: endl" - нет. Вместо этого компилятор выдает ошибку:

main.cpp:10:4: error: no matching function for call to 'operator<<'
    operator<<(std::cout, std::endl);

Q3: Как первый std::cout << "hello1" << std::endl; записываться в форме operator<<(...)?

Если на первые два вопроса был дан ответ, то это, вероятно, уже охвачено. Это пункт этого учебного упражнения, поэтому кажется разумным задавать его явно.

  • 0
    Это очень похоже на домашнюю работу , вопросы, которые нельзя задавать, не зная ответов.
  • 0
    @ Конечно, не часть моей домашней работы! Рад слышать, что мои вопросы звучат хорошо информированно, хотя :)
Показать ещё 2 комментария
Теги:
operator-overloading
cout

4 ответа

3
Лучший ответ

Операторы могут быть реализованы по-разному, в частности, operator<< для которого левая сторона является вашим типом, может быть реализована как свободная функция или как функция-член этого типа левой стороны.

Хотя вы должны реализовать ostream& operator<<(ostream&, MyType const&) как свободную функцию (поскольку MyType не является левой стороной), реализация библиотеки может выбрать * для реализации operator<< для некоторых основных типов insde std::ostream type (который действительно является конкретным экземпляром шаблона, я пытаюсь игнорировать детали).

Изменение: после проверки со стандартом это неверно:

Это то, что вы замечаете в коде, перегрузка, которая принимает const char*, реализуется как член ostream (basic_ostream<char,char_traits<char>).

Перегруженные манипуляторы реализованы как функции-члены (Q2), и существует неявное преобразование из const char* в const void* которое будет выбрано, если вы используете синтаксис для явного вызова оператора-члена (Q1). Для Q3 ответ будет следующим:

operator<<(std::cout, "Hello").operator<<(std::endl);

* Реализация на самом деле не свободна в выборе, поскольку стандарт подпишет подписи.

  • 0
    Посмотрим, пойму ли я это ... Использование operator<< с std::endl (манипулятором) реализовано как функция-член cout (или другого подобного объекта). Так что эта линия работает.
  • 0
    Однако использование operator<< с фундаментальным типом (не обязательно) не реализовано как функция-член ...
Показать ещё 7 комментариев
1

В std::ostream имеется группа операторов вывода std::ostream. Оглядываясь назад, вероятно, это была ошибка, но когда IOStreams были созданы впервые, я думаю, что это было действительно необходимо. Эти операторы-члены включают в себя перегрузки с помощью указателей на функции, что означает, что вам нужно будет использовать обозначение участника для них. Операторы, использующие C-строки, являются перегрузками, отличными от членов, т.е. Для получения перегрузки C-строки вам необходимо использовать нотацию не-членной функции. Когда вы вызываете оператор-член с char const* char const* будет преобразован в void const* для которого существует оператор вывода элемента.

  • 0
    Это преобразование из char const* в void const* звучит противно. Есть ли причина для этого, или просто еще одна жертва явного отказа от использования по умолчанию?
  • 2
    @GnomeDePlume: Что ж, лучшее совпадение для out.operator<< (str) для std::ostream& out и char const* str - это перегрузка std::ostream::operator<< (void const*) и это , таким образом, выбрал. При использовании нотации вызова std::operator<< (std::ostream&, char const*) лучшее совпадение - std::operator<< (std::ostream&, char const*) .
1

Ваши вопросы могут быть разбиты на функции-члены, а не на функции-члены.

Имея 13.5.2 Бинарные операторы

Бинарный оператор должен быть реализован либо нестатической функцией-членом (9.3) с одним параметром, либо не-членной функцией с двумя параметрами. Таким образом, для любого двоичного оператора @, x @y можно интерпретировать как x.оператор @(y) или оператор @(x, y). Если обе формы операторной функции были объявлены, правила в 13.3.1.2 определяют, какая интерпретация используется, если таковая имеется.

Опуская цитату из 13.3.1.2, функция-член (оператор) является предпочтительной.

Строка 'std :: cout << "hello" << std :: endl;' включает нечленовские функции. Каждый 'std :: cout.operator' является явным вызовом функции функции.

  • Q1 - оператор-член << (const void *)
  • Q2 нет члена, принимающего функцию
  • Q3 Невозможно
1

Некоторые перегрузки operator<< являются членами класса, другие - нет.

В C++ 03 это создало несколько проблемных сценариев вызова, поскольку ссылка на non- const (аргумент не-члена) не может быть привязана к значению r, но в C++ 11 по крайней мере один такой был зафиксирован введение перегрузки опорных аргументов rvalue.

Таким образом, вызов, который компилируется или нет, в целом зависит также от версии стандартов C++, C++ 03 или C++ 11.

  • 0
    Я попытался скомпилировать (g ++) с помощью '-std = c ++ 11', но это не имело никакого значения для вызовов в тестовой программе. Полезно знать, хотя!
  • 1
    @GnomeDePlume: на данный момент Codepad - это одна вставка, использующая довольно старый компилятор. так что вы можете посмотреть пример ( codepad.org/h7WXNhuW ). к сожалению, этот код компилируется без ошибок, когда я указываю от -std=c++03 до MinGW g ++ 4.7.2.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню