Форум программистов, компьютерный форум CyberForum.ru

Перегрузка operator<< - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 54, средняя оценка - 4.83
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
17.02.2011, 00:10     Перегрузка operator<< #1
Доброе время суток.

Есть очередная задачка - перегрузить оператор вывода таким образом:

Есть три объекта разных классов - А а, В в, С с;

Нужно, чтобы при записи а << b << c; изменялось значение некоторых членов всех трех классов, ну грубо говоря, пусть там есть по одному члену типа float и пусть при такой записи вывода произойдет нечто вроде
b.f+=0.2*c.f;
a.f+=0.8*c.f;

А при любой другой записи - (b<<c<<a, c<<b<<a, b<<a<<c, a<<b<<a) - пусть проводится просто вывод каких-нибудь членов класса, не суть важно. Или даже ошибка за неправильный порядок членов в выводе.

Можно ли это вообще сделать, а если нельзя, то что требуется от этих трех объектов?

Точно известно, что речь про перегрузку вывода, а не перегрузку сдвига.
С перегрузкой я знаком, но вызывает затруднение именно такой порядок и вообще, наличие 3х объектов, о которых идет речь.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.02.2011, 00:10     Перегрузка operator<<
Посмотрите здесь:

C++ перегрузка operator<<
Перегрузка operator= C++
C++ перегрузка operator[][][]
C++ Перегрузка operator new
C++ Перегрузка operator->()
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
18.02.2011, 21:58  [ТС]     Перегрузка operator<< #21
Господа, получил небольшое облегчение задачи по теме.

Реализуйте класс, описывающий работу фильтра.
Перегрузите операции ввода-вывода так, чтобы при прохождении жидкости через фильтр (операция вида СОСУД << ФИЛЬТР << КОЛБА) в фильтре оставалось какое-то количество воды, заданное заранее в конструкторе в виде процента от исходного объема.

Сдается мне, что это похоже на токенайзер какой-то - разбор выражения типа...

Или может быть даже просто сделать перегрузку оператора ввода, а три больших слова - открытыми членами класса и выводить их. Ну и параллельно менять описываемый объем. Или это слишком просто?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
18.02.2011, 22:02     Перегрузка operator<< #22
Так речь-то всё-таки идёт о перегрузке именно оператора <<, с выводом никак не связанной.
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
19.02.2011, 23:53  [ТС]     Перегрузка operator<< #23
Но ведь написано "перегрузить операторы ввода-вывода"...
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
19.02.2011, 23:55     Перегрузка operator<< #24
Selendis, почитайте обсуждение на прошлой странице о <<
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
20.02.2011, 00:01  [ТС]     Перегрузка operator<< #25
alex_x_x: А разве тут не идет речь о том, чтобы перегрузить <<, который уже был перегружен для basic_ios?(ну или где там cout определяются)

Плюс тут еще есть ввод, который наверное тоже куда-то в тему будет...
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
20.02.2011, 00:11     Перегрузка operator<< #26
Selendis, вы, похоже, не совсем понимаете суть перегрузки. Перегрузить оператор, который уже где-то перегружен, не получится. Везде, где оператор << не перегружен, он будет делать то, что должен делать согласно функциональности, определяемой ядром языка - сдвигать свой левый операнд на столько позиций влево, сколько указано во втором операнде. Вы либо используете его AsIs, либо перегружаете, давая ему новый функционал. То, что он уже где-то перегружен как оператор, отвечающий за вставку данных в поток, нам фиолетово. Мы, как и разработчики стандартного класса работы с потоками, просто перегружаем этот оператор языка так, чтобы он выполнял заданный функционал. По сути таким же образом, каким мы определяем оператор << для своего класса, передавая ему в качестве левого операнда экземпляр класса std::ostream, мы можем определить практически любой бинарный оператор, и радоваться, только потом, когда кто-то будет нашим классом пользоваться, нас проклянёт за такие выкрутасы.

Добавлено через 4 минуты
Вот пример того, как делать можно, но не нужно, чтобы вы убедились, что то, что оператор << называют оператором вывода в поток, определили разработчики стандартных классов работы с потоками. Определи они для этой цели другой оператор, кто знает, может данный код был бы вполне уместен)))

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
 
class Foo
{
public:
    Foo(int a = 0):
    _a(a)
    {
    }
 
    friend std::ostream &operator+(std::ostream &, const Foo &);
 
private:
    int _a;
};
 
std::ostream &operator+(std::ostream &output, const Foo &rhs)
{
    return output << rhs._a;
}
 
int main()
{
    Foo f1(1), f2(2), f3(3);
 
    std::cout + f1 + f2 + f3 << std::endl;
 
    return 0;
}
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
20.02.2011, 00:13  [ТС]     Перегрузка operator<< #27
Ох, вроде бы немного понимал.

Выражусь вот так - прав ли я в том, что здесь требуется перегрузить не просто оператор <<, а скорее оператор <<, точно получающий левым операндом std::ostream?

Ведь грубо говоря, я могу ограничить понятие оператора вывода, определив его как сдвиг, получающий ostream в качестве левого операнда...

И говоря о перегрузке именно оператора вывода, я всего лишь имею в виду то, что у него один операнд определен.

Или же я кругом не прав, и здесь правые и левые операнды уже указаны в задании, а для трех штук(СОСУД << ФИЛЬТР << КОЛБА) мне придется пользоваться его какой-нибудь ассоциативностью?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
20.02.2011, 00:18     Перегрузка operator<< #28
Полагаю, в задании ничего о выводе не сказано, а чётко сказано, что есть три объекта трёх классов, и их определённая последовательность в выражении a << b << c; задаёт определённое поведение программы. Вам же вроде на первой странице отписали несколько вариантов такой реализации, но вы почему-то ухватились за потоки и никак их не отпускаете, хотя в задании о них ничего не говорится.
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
21.02.2011, 00:36  [ТС]     Перегрузка operator<< #29
Ладно, не буду усложнять себе судьбу)
Уважаемый alex_x_x, а как в Вашем коде сделать так, чтобы грубо говоря
"a.value = c.value*b.value", причем только в случае "a<<b<<c" ?

Насколько я понял, там логично кейс для c будет позже кейса для a и обратиться к a уже никак нельзя. И в то же время, операция мне нужна только в случае a<<b<<c.

В голову лезут только вариант сделать глобальные экземпляры класса, вариант статических переменных и вариант сделать операцию явно опосля, достав какую-нибудь логическую переменную из менеджера.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
23.02.2011, 19:26     Перегрузка operator<< #30
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <cassert>
#include <string>
#include <iostream>
 
class Base{
public:
  int value;
  Base( int _value ) : value( _value ) {}
  virtual std::string getName() = 0;
};
 
#define CLASS(NAME)                  \
class NAME : public Base{            \
public:                              \
  NAME( int _value) : Base(_value){} \
  virtual std::string getName(){     \
    return #NAME;                    \
  }                                  \
};                               
 
 
#define BEGIN_SWITCH( COUNT )                \
do{                                          \
  switch( COUNT ) { 
 
#define CASE( NUM, TYPE, OBJ, GOOD, LP )     \
case NUM :                                   \
  if( !dynamic_cast<TYPE*>( OBJ ) ){         \
    GOOD = false;                  \
  }                                                    \
  LP[NUM] = OBJ;                             \
  break;
 
#define END_SWITCH()                         \
  default: assert( 0 );                      \
}} while(0)
 
CLASS(A);
CLASS(B);
CLASS(C);
 
Base& operator<<( Base& a, Base& b ){
  static unsigned uCount = 0;
  static bool bIsGood = true;
  static Base* lpB[3];
 
  std::cout << a.getName() << b.getName() << uCount << bIsGood << std::endl;
 
  BEGIN_SWITCH( uCount )
    CASE( 0, A, &a, bIsGood, lpB )
    CASE( 1, B, &a, bIsGood, lpB )
    CASE( 2, C, &a, bIsGood, lpB )
  END_SWITCH();
  if( 1 == uCount ){
    ++uCount;
    return b << b;
  }else if( 2 == uCount ){
    if( bIsGood ){
      //std::cout << "!\n";
      lpB[0]->value = lpB[1]->value * lpB[2]->value;
    }
    uCount = 0;
    bIsGood = true;
  }else{
    ++uCount;
  }
  return b;
}
 
int main(){
  A a(1);
  B b(2);
  C c(3);
  a << b << c;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
  b << b << c;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
  c << b << a;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
  a << b << c;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
}
вот, насколько я понял

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[alexxx@localhost ~]$ g++ 6.cpp && ./a.out 
AB01
BC11
CC21
6
BB01
BC10
CC20
0
CB01
BA10
AA20
0
AB01
BC11
CC21
6
zykis
Сообщений: n/a
22.03.2014, 17:40     Перегрузка operator<< #31
Доброе время суток.

Есть очередная задачка - перегрузить оператор вывода таким образом:

Есть три объекта разных классов - А а, В в, С с;

Нужно, чтобы при записи а << b << c; изменялось значение некоторых членов всех трех классов, ну грубо говоря, пусть там есть по одному члену типа float и пусть при такой записи вывода произойдет нечто вроде
b.f+=0.2*c.f;
a.f+=0.8*c.f;

А при любой другой записи - (b<<c<<a, c<<b<<a, b<<a<<c, a<<b<<a) - пусть проводится просто вывод каких-нибудь членов класса, не суть важно. Или даже ошибка за неправильный порядок членов в выводе.

Можно ли это вообще сделать, а если нельзя, то что требуется от этих трех объектов?

Точно известно, что речь про перегрузку вывода, а не перегрузку сдвига.
С перегрузкой я знаком, но вызывает затруднение именно такой порядок и вообще, наличие 3х объектов, о которых идет речь.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
 
class B {};
class C {};
class A {
public:
    A operator <<(B b);
    void operator<< (C c);
};
 
A A::operator <<(B b)
{
    //ваш код
    return *this;
}
 
void A::operator <<(C c)
{
   //ваш код
}
 
A aa;
B bb;
C cc;
 
int main()
{
    aa << bb << cc;
//    аналогично вызову
//    (aa.operator <<(bb)).operator <<(cc);
    return 0;
}
Stitch Igorek
 Аватар для Stitch Igorek
44 / 44 / 17
Регистрация: 02.04.2016
Сообщений: 300
Завершенные тесты: 1
22.04.2016, 09:30     Перегрузка operator<< #32
Цитата Сообщение от silent_1991 Посмотреть сообщение
компилятор развернёт arr[i] в *(arr + i)
Компилятор то развернет, только запись *(arr + i), более быстродейственна, чем arr[i]. Ну по крайней мере так написано в учебниках.
nimazzzy
22.04.2016, 09:39
  #33

Не по теме:

Цитата Сообщение от Stitch Igorek Посмотреть сообщение
только запись *(arr + i), более быстродейственна, чем arr[i].
Нет.

Stitch Igorek
 Аватар для Stitch Igorek
44 / 44 / 17
Регистрация: 02.04.2016
Сообщений: 300
Завершенные тесты: 1
22.04.2016, 14:34     Перегрузка operator<< #34
Цитата Сообщение от nimazzzy Посмотреть сообщение
Нет.
В языке С существуют два метода обращения к элементу массива: адресная арифметика и индексация массива. Стандартная запись массивов с индексами наглядна и удобна в использовании, однако с помощью адресной арифметики иногда удается сократить время доступа к элементам массива. Поэтому адресная арифметика часто используется в программах, где существенную роль играет быстродействие.

<- цитата с сайта http://cpp.com.ru/shildt_spr_po_c/05/0505.html
zss
Модератор
Эксперт С++
 Аватар для zss
5948 / 5553 / 1785
Регистрация: 18.12.2011
Сообщений: 14,188
Завершенные тесты: 1
22.04.2016, 14:38     Перегрузка operator<< #35
Цитата Сообщение от Stitch Igorek Посмотреть сообщение
иногда удается сократить время доступа к элементам
Имеется ввиду, например, итераторное обращение к элементам:
C++
1
2
for(int* p=arr;p!=arr+size;++p)
   cout<< *p;
IGPIGP
Комп_Оратор)
 Аватар для IGPIGP
6172 / 2901 / 284
Регистрация: 04.12.2011
Сообщений: 7,714
Записей в блоге: 3
22.04.2016, 14:41     Перегрузка operator<< #36
Тема поднята из глубин небытия, но поскольку всё "новое", это хорошо забытое "старое" хочется что-то изваять. Вот тут тема о вычитании строк:
Написать перегрузку оператора "минус" для строк
Поэтому чуть переделав тот исходник попробую пошутить в этой теме)
Я конечно против перегрузок с неожиданными побочными эффектами, но ради интереса:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <iostream>
using namespace std; 
struct Inta
{
int a;
Inta():a(0){}//по умолчанию
Inta(const int rhs):a(rhs){}//преобразования
Inta(const Inta &rhs):a(rhs.a){}//копирующий
Inta &operator=(Inta &rhs)//присваивания
{
a=rhs.a;
return *this; 
}
 
friend
ostream &operator<<(ostream &os, Inta &rhs);
};
 
struct Intb
{
int b;
Intb():b(0){}//по умолчанию
Intb(const int rhs):b(rhs){}//преобразования
Intb(const Intb &rhs):b(rhs.b){}//копирующий
Intb &operator=(Intb &rhs)//присваивания
{
b=rhs.b;
return *this; 
}
 
friend
ostream &operator<<(ostream &os, Intb &rhs);
};
struct Intc
{
int c;
Intc():c(0){}//по умолчанию
Intc(const int rhs):c(rhs){}//преобразования
Intc(const Intc &rhs):c(rhs.c){}//копирующий
Intc &operator=(Intc &rhs)//присваивания
{
c=rhs.c;
return *this; 
}
 
friend
ostream &operator<<(ostream &os, Intb &rhs);
};
 
struct ABC_out_sequence_Checker
{
static Inta * pa;
static Intb * pb;
static Intc * pc;
static ABC_out_sequence_Checker* ABC_checker;
ostream &cacaut(ostream &os)
{
 
if(pa!=NULL && pb!=NULL && pc!=NULL)
{
//тут поля для вывода в нашем распоряжении и мы можем их изменить: 
pa->a=pb->b+pc->c;//например так
pb->b=pc->c*pa->a;//так
pc->c=pb->b/(pa->a+1);//и так
os<<pa->a<<'\t'<<pb->b<<'\t'<<pc->c;
pa=NULL;
pb=NULL;
pc=NULL;
}
return os;
}
ABC_out_sequence_Checker *get_ABC_ptr()
{
static ABC_out_sequence_Checker abc;
if(ABC_checker==NULL)ABC_checker=&abc;
return ABC_checker;
}
private:
ABC_out_sequence_Checker()
{
if(ABC_checker==NULL)ABC_checker=this;
}
};
Inta *
ABC_out_sequence_Checker::pa = NULL;
Intb *
ABC_out_sequence_Checker::pb = NULL;
Intc *
ABC_out_sequence_Checker::pc = NULL;
 
ABC_out_sequence_Checker*
ABC_out_sequence_Checker::ABC_checker=NULL;
ostream &
operator<<(ostream &os, Inta &rhs)
{
    
    if(
        ABC_out_sequence_Checker::ABC_checker->pa==NULL &&
        ABC_out_sequence_Checker::ABC_checker->pb==NULL &&
        ABC_out_sequence_Checker::ABC_checker->pc==NULL
        )
    {
ABC_out_sequence_Checker::ABC_checker->pa=&rhs;
    }
    
    return ABC_out_sequence_Checker::ABC_checker->cacaut(os);
}
ostream &
operator<<(ostream &os, Intb &rhs)
{
    if(
        ABC_out_sequence_Checker::ABC_checker->pa!=NULL &&
        ABC_out_sequence_Checker::ABC_checker->pb==NULL &&
        ABC_out_sequence_Checker::ABC_checker->pc==NULL
        )
    {
ABC_out_sequence_Checker::ABC_checker->pb=&rhs;
    }   
return ABC_out_sequence_Checker::ABC_checker->cacaut(os);
}
ostream &
operator<<(ostream &os, Intc &rhs)
{
    if(
        ABC_out_sequence_Checker::ABC_checker->pa!=NULL &&
        ABC_out_sequence_Checker::ABC_checker->pb!=NULL &&
        ABC_out_sequence_Checker::ABC_checker->pc==NULL
        )
    {
ABC_out_sequence_Checker::ABC_checker->pc=&rhs;
    }   
return ABC_out_sequence_Checker::ABC_checker->cacaut(os);
}
 
int main()
{
 
Inta a(1);
Intb b(2);
Intc c(3);
 
cout<<a<<b<<c<<endl;
cout<<b<<a<<c;
cout<<c<<a<<b;
cout<<a<<b<<c<<endl;
cin.get();
return 0;    
}

зы прошу извинить за то что не в тему последнего поднятого вопроса
Stitch Igorek
 Аватар для Stitch Igorek
44 / 44 / 17
Регистрация: 02.04.2016
Сообщений: 300
Завершенные тесты: 1
22.04.2016, 17:33     Перегрузка operator<< #37
Цитата Сообщение от zss Посмотреть сообщение
Имеется ввиду, например, итераторное обращение к элементам:
C++
1
2
for(int* p=arr;p!=arr+size;++p)
* *cout<< *p;
если нет никакой разницы с этим
C++
1
2
for(int i(0); i < size; i++)
* *cout<< arr[i];
то для чего указатель создавать(еще при том условии, что указатель в win_64 равен 8 байт, а int - 4).
К тому же твой вариант цикла будет весьма интересно работать, если параметром arr будет строка=).
nimazzzy
22.04.2016, 17:40
  #38

Не по теме:

Цитата Сообщение от Stitch Igorek Посмотреть сообщение
если нет никакой разницы с этим
C++Выделить код
1
2
for(int i(0); i < size; i++)
* *cout<< arr[i];
Разница есть. Операция сложения раз: i++, операция сложения два: arr[i]
C
1
2
for(int* p=arr;p!=arr+size;++p)
    cout<< *p;
Операция сложения раз: ++p. Все.
А вот *(arr + i) и arr[i] - никакой разницы, сколько бы ты не цитировал Шилдта.

avgoor
562 / 352 / 83
Регистрация: 05.12.2015
Сообщений: 1,137
22.04.2016, 17:44     Перегрузка operator<< #39
Цитата Сообщение от Stitch Igorek Посмотреть сообщение
*(arr + i), более быстродейственна, чем arr[i]
Записи *(arr+i) и arr[i] - эквивалентны.
Что выведет эта программа?
C++
1
2
3
4
5
#include <iostream>
int main()
{
    std::cout<<1["abcd"];
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.04.2016, 12:20     Перегрузка operator<<
Еще ссылки по теме:

Перегрузка operator-> () C++
C++ Перегрузка operator<()
C++ Перегрузка operator=

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Stitch Igorek
 Аватар для Stitch Igorek
44 / 44 / 17
Регистрация: 02.04.2016
Сообщений: 300
Завершенные тесты: 1
23.04.2016, 12:20     Перегрузка operator<< #40
при помощи этого кода выяснилось, что разница хоть и не большая - но есть.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <time.h>
 
int main()
{
    const int size(30000);
    int arr[size];
    srand(time(NULL));
    //рандомно заполняем массив
    for (int i(0); i < size; i++)
    {
        arr[i] = rand() % 200;
    }
 
    clock_t start, end;
    //засекаем время
    start = clock();
    //сортируем пузырьком обращаясь к массиву при помощи индексации
    for (int i(0); i < (size - 1); i++)
        for (int j(i); j < size; j++)
            if (arr[i] > arr[j])
            {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
    //останавливаем время - выводим на консоль результат
    end = clock();
    std::cout << ((double)end - start) / ((double)CLOCKS_PER_SEC) << std::endl;
    //снова рандомно заполняем
    for (int i(0); i < size; i++)
    {
        arr[i] = rand() % 200;
    }
    //снова засекаем время
    start = clock();
    //снова сортируем пузырьком, но уже обращаемся к элементам массива с помощью адресной арифметики
    for (int i(0); i < (size - 1); i++)
        for (int j(i); j < size; j++)
            if (*(arr + i) > *(arr + j))
            {
                int temp = *(arr + i);
                *(arr + i) = *(arr + j);
                *(arr + j) = temp;
            }
    //снова останавливаем время - выводим на консоль результат
    end = clock();
    std::cout << ((double)end - start) / ((double)CLOCKS_PER_SEC) << std::endl;
 
    system("pause");
    return 0;
}
100.000 элементов первый вариант сортировал 10,633 сек, второй вариант 10,451.
Yandex
Объявления
23.04.2016, 12:20     Перегрузка operator<<
Ответ Создать тему
Опции темы

Текущее время: 16:22. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru