Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/41: Рейтинг темы: голосов - 41, средняя оценка - 4.56
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42

Класс не содержит подходящий конструктор копий

30.07.2021, 00:45. Показов 9272. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
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
class Matrix
{
private:
    void mallocate(int height, int width);
public:
    double* operator[](int x)
    {
        return matr[x];
    }
    Matrix operator+(Matrix sec);
    Matrix operator=(Matrix sec);
    int height;
    int width;
    double** matr;
    Matrix(int height, int width);
    Matrix(int height, int width, double value);
    Matrix(Matrix& anoth);
    void show();
    ~Matrix();
};
int main()
{
    srand((unsigned int)time(NULL));
    Matrix A(5, 8), C(5,8);
    Matrix B = A;
    C = A + B;
    return EXIT_SUCCESS;
}
Matrix::Matrix(Matrix& anoth)
{
    mallocate(anoth.height, anoth.width);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = anoth[i][j];
        }
    }
}
Matrix Matrix::operator+(Matrix sec)
{
    if (height == sec.height && width == sec.width)
    {
        Matrix tmp(height, width);
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                tmp[i][j] = matr[i][j] + sec[i][j];
            }
        }
        return tmp;
    }
    else
    {
        perror("\nError: Matrixes' sizes (addition)");
        exit(EXIT_FAILURE);
    }
}
 
Matrix Matrix::operator=(Matrix sec)
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = sec[i][j];
        }
    }
    return *this;
}
Подчеркивается строка
C++
1
C = A + B;
, хотя переопределенный оператор "+" как раз возвращает объект типа Matrix. Как можно исправить данную ошибку?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.07.2021, 00:45
Ответы с готовыми решениями:

Класс "String" не содержит подходящий конструктор копий
При компиляции в строке 24 мэйна &quot;cout &lt;&lt; (str + str2);&quot; происходит ошибка : &quot;класс &quot;String&quot; не содержит подходящий конструктор...

Ошибка E0334 класс "Complex" не содержит подходящий конструктор копий
Помогите, пожалуйста, исправить ошибки В данном коде из лаботорной ошибки E0334 класс &quot;Complex&quot; не содержит подходящий...

Конструктор копий и оператор присвоения копий
Есть ли какие-то правила для того как имеено копировать переменные-члены объектов в конструкторе и операторе? Тоесть есть ли разница...

14
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12928 / 6796 / 1819
Регистрация: 18.10.2014
Сообщений: 17,194
30.07.2021, 01:46
Цитата Сообщение от Даниил154 Посмотреть сообщение
Класс не содержит подходящий конструктор копий
Да, до С++14 включительно это ошибка. Вы предаете параметр оператора присваивания по копии, значит нужен конструктор копии.

Ваш конструктор копии вызвать невозможно, потому что параметр у него - неконстантная ссылка. Почему у вас параметр конструктора копирования - неконстантная ссылка?

И разу уж вы написали такой [странный] оператор присваивания, то почему у вас параметр оператора присваивания передается по копии? Зачем здесь дополнительная копия?
0
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42
30.07.2021, 08:34  [ТС]
Спасибо! Не могли бы вы пояснить: почему в строке
C++
1
Matrix B = A;
конструктор копии отрабатывает правильно, а в случае
C++
1
C = A + B;
нет?
И есть ли принципиальная разница в использовании именно константной ссылки, кроме безопасности?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12928 / 6796 / 1819
Регистрация: 18.10.2014
Сообщений: 17,194
30.07.2021, 09:07
Лучший ответ Сообщение было отмечено Даниил154 как решение

Решение

Цитата Сообщение от Даниил154 Посмотреть сообщение
есть ли принципиальная разница в использовании именно константной ссылки, кроме безопасности?
Принципиальная разница заключается в том, что константную ссылку можно привязывать к временным объектам. А неконстантную - нельзя.

Цитата Сообщение от Даниил154 Посмотреть сообщение
Matrix B = A;
Здесь в правой части стоит обыкновенный (не временный) объект, поэтому неконстантная ссылка к нему привязывается.

Цитата Сообщение от Даниил154 Посмотреть сообщение
C = A + B;
А здесь в правой части стоит временный объект. Неконстантную ссылку к нему привязать нельзя.
1
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42
30.07.2021, 14:03  [ТС]
Спасибо! Теперь все ясно

Добавлено через 4 часа 49 минут
По поводу
C++
1
C = A + B;
Конструктор копирования срабатывает для временного объекта A + B, копирование происходит в него из функции, перегружающей оператор "+". Но так как копирование происходит в этот объект, ссылка чего передается в конструктор? Или я ошибаюсь?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.07.2021, 14:14
Цитата Сообщение от Даниил154 Посмотреть сообщение
ссылка чего передается в конструктор?
Временный объект может быть сконструирован из локального объекта-результата сложения A и B внутри оператора +.
Т.е. ссылка будет на этот локальный экземпляр.

Вот пример для наглядности: https://rextester.com/CPJ11423
0
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42
30.07.2021, 14:42  [ТС]
Если ссылка
Цитата Сообщение от DrOffset Посмотреть сообщение
на этот локальный экземпляр
то почему она обязательно должна быть константной?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.07.2021, 15:00
Цитата Сообщение от Даниил154 Посмотреть сообщение
то почему она обязательно должна быть константной?
Посмотрите внимательно пример.
Вы видите в логе ДВА вызова конструктора копирования. Первый конструктор копирования вызывается от локального ret и там действительно ссылка не обязана быть константной.
А вот второй конструктор копирования - как раз с ним и был связан изначальный вопрос - вызывается от временного объекта, который копируется в C и в этом случае ссылка обязана быть константной.

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
class Matrix
{
public:
    Matrix() { std::cout << "Matrix()\n"; }
    Matrix(Matrix const & x) { std::cout << "Matrix(Matrix const &)\n"; }
    
    Matrix operator+(Matrix const &) const {
        Matrix ret;
        
        return ret;
    }
};
 
int main()
{
    Matrix A, B;
    
    Matrix C = A + B;
}


Однако выше вы спросили
Цитата Сообщение от Даниил154 Посмотреть сообщение
Конструктор копирования срабатывает для временного объекта A + B, копирование происходит в него из функции, перегружающей оператор "+". Но так как копирование происходит в этот объект, ссылка чего передается в конструктор?
подразумевая под "этим объектом" - временный. Поэтому и получили такой ответ от меня: временный объект конструируется из локального экземпляра.
0
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42
30.07.2021, 15:18  [ТС]
C++
1
C = A + B;
Дело в том, что компилятор ругался на данную строку. В ней происходит копирование конструктором только из функции, те объект C тут не инициализируется, он был проинициализирован выше.
Ошибка пропала, когда я поменял параметр конструктора копирования на константную ссылку.
Вот я и пытаюсь понять, в чем заключалась ошибка.
Цитата Сообщение от DrOffset Посмотреть сообщение
Первый конструктор копирования вызывается от локального ret и там действительно ссылка не обязана быть константной
Так получается, что ошибки не должно было быть?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.07.2021, 15:40
Лучший ответ Сообщение было отмечено Даниил154 как решение

Решение

Цитата Сообщение от Даниил154 Посмотреть сообщение
Так получается, что ошибки не должно было быть?
Мне пока не понятно о чем именно вы спрашиваете, поэтому воздержусь от ответа.

Цитата Сообщение от Даниил154 Посмотреть сообщение
Дело в том, что компилятор ругался на данную строку. В ней происходит копирование конструктором только из функции, те объект C тут не инициализируется, он был проинициализирован выше.
Ошибка пропала, когда я поменял параметр конструктора копирования на константную ссылку.
Вот я и пытаюсь понять, в чем заключалась ошибка.
Вот такой код имеется в виду?
C++
1
2
3
4
5
6
7
int main()
{
    Matrix A, B;
    
    Matrix C;
    C = A + B;
}
Покажите ПОЛНЫЙ КОПИЛИРУЕМЫЙ пример, в котором проявляется ошибка, о которой вы говорите.

Добавлено через 6 минут
Хотя можно и не показывать. Я забыл, что у вас там был такой оператор:
Цитата Сообщение от Даниил154 Посмотреть сообщение
Matrix Matrix::operator=(Matrix sec)
В таком случае вот ответы:
Цитата Сообщение от Даниил154 Посмотреть сообщение
Так получается, что ошибки не должно было быть?
Должна быть.

Цитата Сообщение от Даниил154 Посмотреть сообщение
те объект C тут не инициализируется
Объект C не инициализируется (он присваивается), зато инициализируется параметр функции operator= sec.
Он инициализируется конструктором копирования от временного объекта, который является результатом сложения A и B.

Кликните здесь для просмотра всего текста

Для простоты не затрагиваем темы временной материализации и категории выражений, чтобы не запутать автора.
1
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42
30.07.2021, 15:41  [ТС]
Вот полный пример. Он не компилируется из-за ошибки, однако, если добавить const в параметры конструктора копирования - ошибка припадает, код компилируется.
Я пытаюсь понять естество данной ошибки.

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
class Matrix
{
private:
    void mallocate(int height, int width);
public:
    double* operator[](int x)
    {
        return matr[x];
    }
    Matrix operator+(Matrix sec);
    Matrix operator=(Matrix sec);
    int height;
    int width;
    double** matr;
    Matrix(int height, int width);
    Matrix(int height, int width, double value);
    Matrix(Matrix& anoth);
    void show();
    ~Matrix()
    {
        for (int i = 0; i < height; i++)
        {
            delete[] matr[i];
        }
        delete[] matr;
    }
};
 
int main()
{
    srand((unsigned int)time(NULL));
    Matrix A(5, 8), C(5,8);
    A.show();
    Matrix B = A;
    B.show();
    C = A + B;
    C.show();
    return EXIT_SUCCESS;
}
 
void Matrix::mallocate(int height, int width)
{
    matr = NULL;
    this->height = height;
    this->width = width;
    matr = new double* [this->height];
    if (matr == NULL)
    {
        perror("\nWARNING!");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < height; i++)
    {
        matr[i] = new double[this->width];
    }
}
 
Matrix::Matrix(int height, int width)
{
    double random = 0.0;
    mallocate(height, width);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            random = rand() % 20;
            matr[i][j] = random - 10.0;
        }
    }
}
 
Matrix::Matrix(int height, int width, double value)
{
    mallocate(height, width);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = value;
        }
    }
}
 
Matrix::Matrix(Matrix& anoth)
{
    mallocate(anoth.height, anoth.width);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = anoth.matr[i][j];
        }
    }
}
 
void Matrix::show()
{
    std::cout << "\n";
    for (int i = 0; i < height; i++)
    {
        std::cout << " ";
        for (int j = 0; j < width; j++)
        {
            if (matr[i][j] >= 0)
                std::cout << matr[i][j] << "   ";
            else 
                std::cout << matr[i][j] << "  ";
        }
        std::cout << "\n";
    }
    std::cout << "____________";
}
 
Matrix Matrix::operator+(Matrix sec)
{
    if (height == sec.height && width == sec.width)
    {
        Matrix tmp(height, width);
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                tmp.matr[i][j] = matr[i][j] + sec.matr[i][j];
            }
        }
        return tmp;
    }
    else
    {
        perror("\nError: Matrixes' sizes (addition)");
        exit(EXIT_FAILURE);
    }
}
 
Matrix Matrix::operator=(Matrix sec)
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = sec.matr[i][j];
        }
    }
    return *this;
}
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.07.2021, 15:47
Даниил154, исправил ваш пример:
Кликните здесь для просмотра всего текста
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
149
150
//clang 6.0.0
#include <cstdlib>
#include <ctime>
#include <iostream>
 
class Matrix
{
private:
    void mallocate(int height, int width);
public:
    double* operator[](int x)
    {
        return matr[x];
    }
    Matrix operator+(Matrix sec);
    Matrix operator=(const Matrix &sec);
    int height;
    int width;
    double** matr;
    Matrix(int height, int width);
    Matrix(int height, int width, double value);
    Matrix(Matrix& anoth);
    void show();
    ~Matrix()
    {
        for (int i = 0; i < height; i++)
        {
            delete[] matr[i];
        }
        delete[] matr;
    }
};
 
int main()
{
    srand((unsigned int)time(NULL));
    Matrix A(5, 8), C(5,8);
    A.show();
    Matrix B = A;
    B.show();
    C = A + B;
    C.show();
    return EXIT_SUCCESS;
}
 
void Matrix::mallocate(int height, int width)
{
    matr = NULL;
    this->height = height;
    this->width = width;
    matr = new double* [this->height];
    if (matr == NULL)
    {
        perror("\nWARNING!");
        exit(EXIT_FAILURE);
    }
    for (int i = 0; i < height; i++)
    {
        matr[i] = new double[this->width];
    }
}
 
Matrix::Matrix(int height, int width)
{
    double random = 0.0;
    mallocate(height, width);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            random = rand() % 20;
            matr[i][j] = random - 10.0;
        }
    }
}
 
Matrix::Matrix(int height, int width, double value)
{
    mallocate(height, width);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = value;
        }
    }
}
 
Matrix::Matrix(Matrix& anoth)
{
    mallocate(anoth.height, anoth.width);
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = anoth.matr[i][j];
        }
    }
}
 
void Matrix::show()
{
    std::cout << "\n";
    for (int i = 0; i < height; i++)
    {
        std::cout << " ";
        for (int j = 0; j < width; j++)
        {
            if (matr[i][j] >= 0)
                std::cout << matr[i][j] << "   ";
            else 
                std::cout << matr[i][j] << "  ";
        }
        std::cout << "\n";
    }
    std::cout << "____________";
}
 
Matrix Matrix::operator+(Matrix sec)
{
    if (height == sec.height && width == sec.width)
    {
        Matrix tmp(height, width);
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                tmp.matr[i][j] = matr[i][j] + sec.matr[i][j];
            }
        }
        return tmp;
    }
    else
    {
        perror("\nError: Matrixes' sizes (addition)");
        exit(EXIT_FAILURE);
    }
}
 
Matrix Matrix::operator=(const Matrix & sec)
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            matr[i][j] = sec.matr[i][j];
        }
    }
    return *this;
}

Конструктор копирования остался с неконстантной ссылкой, а оператор присваивания теперь принимает костантную ссылку (чтобы иметь возможность привязать временный объект).
0
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,531
Записей в блоге: 1
30.07.2021, 15:52
Даниил154, а в чём если не секрет такое упорное желание запретить копировать константные объекты? (путём убирания const)
0
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42
30.07.2021, 15:57  [ТС]
Спасибо огромное!

Добавлено через 1 минуту
Упорного желания нет, просто я учусь. Хочу понимать, как все работает.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
30.07.2021, 16:10
Цитата Сообщение от Даниил154 Посмотреть сообщение
Я правильно понимаю, временный объект может передаваться в данном случае ТОЛЬКО по константной ссылке и никак иначе?
Через rvalue-reference еще может.


PS.
На самом деле не совсем корректно в данном случае говорить об объектах, потому что в первую очередь рассматриваются выражения.

Результаты выражений, категории которых является rvalue, могут быть привязаны либо к константным ссылкам, либо к rvalue-ссылкам. Временный объект в этих выражениях может появляться, а может и не появляться, это тут не главное.

Но вам, конечно, на данном этапе будет удобнее рассуждать именно в терминах объектов, хоть это и несколько некорректно.
Тем не менее, вот ссылка для последующего ознакомления https://en.cppreference.com/w/... e_category

Добавлено через 4 минуты
Цитата Сообщение от Даниил154 Посмотреть сообщение
ТОЛЬКО по константной ссылке
Думаю, будет полезным также узнать первопричины такого поведения: Особенности ссылок
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.07.2021, 16:10
Помогаю со студенческими работами здесь

Класс не содержит конструктор, который принимает аргументы
Утро доброе, пытаюсь вывести картинку, но пишет: &quot;Employee не содержит конструктор, который принимает аргумент 2&quot; Я так понимаю, у...

Класс не содержит конструктор, принимающий 3 аргумента: найти ошибку в коде
Весь измучился, но компилятор неприклонен - &quot;Ошибка 1 SAYAP_labaratornaya2.Student не содержит конструктор, который принимает 3...

Класс формы не содержит конструктор, который принимает один аргумент
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using...

Написать базовый абстрактный класс который содержит универсальные поля для банковского счета и конструктор
Научиться использовать наследование и организацию структур . 1. Написать базовый абстрактный класс который содержит универсальные поля...

Шаблонный класс (конструктор по умолчанию, основной конструктор и конструктор копирования; перегрузить операторные функции)
5.1. Разработать шаблонный класс Set. Класс должен содержать конструктор по умолчанию, основной конструктор и конструктор копирования....


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Ниже машинный перевод статьи The Thinkpad X220 Tablet is the best budget school laptop period . Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы,. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru