ostream::operator<<();

118
20 июля 2019, 13:10

вот код:

cout.operator<<("Hello");//он выводит вместо строки какие-то шестнадцетиричные числа 01337BD8P

фактически тот же самый код:

cout << "Hello";//выводит строку 
operator<<(cout,"Hello");//тоже выводит строку 

В чем разница между записями?

Answer 1

basic_ostream для указателей существует несколько перегрузок operator<<. Часть из этих перегрузок выполнена в качестве функций-членов класса, а часть как внешние функции.

В определении самого класса для указательных типов имеется только перегрузка для параметра типа void *

template<class charT, class traits = char_traits<charT>>
class basic_ostream : virtual public basic_ios<charT, traits> {
public:
    ...
    basic_ostream<charT, traits>& operator<<(const void* p);
    ...
};

При вызове

cout.operator<<("Hello");

вызывается именно функция-член класса, а других подходящих вариантов перегрузки нет: "Hello" - массив char[6], который может быть неявно преобразован в char const *, который в свою очередь преобразуется в void const * поэтому и выводится адрес, в соответствии с поведением данной перегрузки.

Перегрузки, принимающие char const * объявлены как внешние функции:

template<class charT, class traits>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const char*);
template<class traits>
basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char*);

В коде

operator<<(cout, "Hello");

явно вызывается внешняя функция operator<<, поэтому функции-члены basic_ostream даже не рассматриваются. Естественно, это приводит к выводу строки в соответствии с поведением перегрузки для char const *

Код

cout << "Hello";

приводит к рассмотрению перегрузок operator<< объявленных как функции-члены basic_ostream, и как внешних функций. При выборе соответствующих перегрузок, перегрузка с параметром char const * оказывается более подходящей, чем остальные, поэтому выбирается соответствующая внешняя операторная функция.

Answer 2

Для классов большинство операторов вида X ■ Y (включая <<) можно перегружать двумя способами:

  • В виде методов (функций-членов класса): struct A { … operator■(…){…} };
  • В виде свободных (обычных) функций: struct A {}; int operator■(…, …){…}

Когда вы пишете X.operator■(Y), компилятор учитывает только те перегрузки , которые сделаны в виде методов.

Когда вы пишете operator■(X, Y), компилятор учитывает только те перегрузки, которые сделаны в виде свободных функций.

Когда вы пишете X ■ Y, компилятор учитывает оба варианта перегрузок.

Похоже, что для std::cout оператор << для разных типов перегружен разными способами.

Для const char * (печать строки) он перегружен как свободная функция, а для const void * (печать адреса) он перегружен как метод.

Когда вы пишете cout << "Hello";, выбирается перегрузка с параметром const char * (свободная функция), потому что она подходит лучше, чем та, что с параметром const void * (метод), и чем все остальные варианты.

Когда вы пишете operator<<(cout,"Hello");, рассматриваются только перегрузки в виде свободных функций. Из них выбирается та же самая перегрузка, с параметром const char *. А вариант с параметром const void * не рассматривается вообще, потому что это - метод.

А вот когда вы пишете cout.operator<<("Hello");, вариант с const char * не рассматривается, и из перегрузок-методов выбирается const void *, потому что он подходит лучше других вариантов.

READ ALSO
Ошибка при удалении элемента в deque через итератор

Ошибка при удалении элемента в deque через итератор

myDequeerase(min) выдает ошибку: cannot seek value-initialized deque iterator

116
Параметр функции в c++

Параметр функции в c++

Вкратце можно сказать следующее

116
Как сравнить изображения на java?

Как сравнить изображения на java?

Есть ли встроенные методы, позволяющие сравнить изображения на полное сходство (Не просто == или imgequals(img2), ибо в первом это разные объекты,...

121
Android, java, view.setOnTouchListener

Android, java, view.setOnTouchListener

Был у меня recyclerview с адаптером и все было крутоЯ добавил view

121