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

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

30.07.2021, 00:45. Показов 9402. Ответов 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
13192 / 6827 / 1822
Регистрация: 18.10.2014
Сообщений: 17,277
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
13192 / 6827 / 1822
Регистрация: 18.10.2014
Сообщений: 17,277
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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,536
Записей в блоге: 1
30.07.2021, 15:52
Даниил154, а в чём если не секрет такое упорное желание запретить копировать константные объекты? (путём убирания const)
0
0 / 0 / 0
Регистрация: 25.01.2019
Сообщений: 42
30.07.2021, 15:57  [ТС]
Спасибо огромное!

Добавлено через 1 минуту
Упорного желания нет, просто я учусь. Хочу понимать, как все работает.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
Ответ Создать тему
Новые блоги и статьи
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru