Это связано с вопросом разницы между 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;
}
std::cout.operator<<("hello2");
Работа? Из других ответов на SO я ожидал бы, что компилятор будет жаловаться, поскольку operator<<
означает свободную функцию, а не член cout
. Однако в моей системе он печатает "0x10d54df31". И, еще более странно, следующая строка правильно корректно выполняет std::endl
.
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);
std::cout << "hello1" << std::endl;
записываться в форме operator<<(...)
?Если на первые два вопроса был дан ответ, то это, вероятно, уже охвачено. Это пункт этого учебного упражнения, поэтому кажется разумным задавать его явно.
Операторы могут быть реализованы по-разному, в частности, 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);
* Реализация на самом деле не свободна в выборе, поскольку стандарт подпишет подписи.
operator<<
с std::endl
(манипулятором) реализовано как функция-член cout
(или другого подобного объекта). Так что эта линия работает.
operator<<
с фундаментальным типом (не обязательно) не реализовано как функция-член ...
В std::ostream
имеется группа операторов вывода std::ostream
. Оглядываясь назад, вероятно, это была ошибка, но когда IOStreams были созданы впервые, я думаю, что это было действительно необходимо. Эти операторы-члены включают в себя перегрузки с помощью указателей на функции, что означает, что вам нужно будет использовать обозначение участника для них. Операторы, использующие C-строки, являются перегрузками, отличными от членов, т.е. Для получения перегрузки C-строки вам необходимо использовать нотацию не-членной функции. Когда вы вызываете оператор-член с char const*
char const*
будет преобразован в void const*
для которого существует оператор вывода элемента.
char const*
в void const*
звучит противно. Есть ли причина для этого, или просто еще одна жертва явного отказа от использования по умолчанию?
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*)
.
Ваши вопросы могут быть разбиты на функции-члены, а не на функции-члены.
Имея 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' является явным вызовом функции функции.
Некоторые перегрузки operator<<
являются членами класса, другие - нет.
В C++ 03 это создало несколько проблемных сценариев вызова, поскольку ссылка на non- const
(аргумент не-члена) не может быть привязана к значению r, но в C++ 11 по крайней мере один такой был зафиксирован введение перегрузки опорных аргументов rvalue.
Таким образом, вызов, который компилируется или нет, в целом зависит также от версии стандартов C++, C++ 03 или C++ 11.
-std=c++03
до MinGW g ++ 4.7.2.