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

Перегрузка оператора * - C++

Восстановить пароль Регистрация
 
Grinning liar!
3 / 3 / 0
Регистрация: 01.11.2012
Сообщений: 38
27.12.2012, 00:32     Перегрузка оператора * #1
Здрасте.
Есть задача: Реализовать класс Matrix размерностью NxN, в которой хранятся числа типа float. Память под элементы выделять динамически. Перегрузить операции *, =. В функции main привести примеры реализации класса Matrix.
Чтобы упростить себе жизнь, перегружаю * только для умножения на число (хотя бы для начала)
Немножко подчитав книжку, перешел к делу. Все, что на данный момент удалось наработать, ниже:

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
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <conio.h>
 
using namespace std;
 
class Matrix{ 
public:
 
    int size;
 
    float **mas;
    float** create_mas (int);                   //метод создания матрицы
//  void delete_mem ();                         //очистка выделенной памяти
    Matrix const operator* (float x) const;     //перегрузка оператора
};
 
    
void main ()
{
    setlocale (LC_ALL, "Russian");          //подключение локального стандарта
    
//  const float x = 5;                      //тупо число, на которое хотелось бы умножить
    Matrix m1;                              //объявление объекта m1 класса Matrix
    int N;                                  //размер матрицы
 
    cout << "Введите размерность квадратной матрицы" << endl;
    cin >> N;
    
    m1.size = N;
    m1.create_mas(N);                   //создание матрицы и ее вывод на экран
 
    _getch();
 
}
 
 
float** Matrix::create_mas (int size){
 
    float **mas = new float *[size];        //выделяем память на массив указателей начал строк массива
 
    for (int i = 0; i < size; i++)          //выделение памяти на каждую строку массива
        {
            mas[i] = new float [size];
        }
 
        for (int i = 0; i < size; i++)      //заполняем массив числами
            for (int j = 0; j < size; j++)
                cin >> mas[i][j];
 
        for (int i = 0; i < size; i++)      //выводим первоначальный массив на экран
        {
                for (int j = 0; j < size; j++)
                    cout << setw(4) << mas[i][j] << " ";
                cout << endl;
        }
 
        return mas;
}
 
[I]Matrix const Matrix::operator* (float x) const {
 
    for (int i = 0; i < size; i++)      //заполняем массив числами
        for (int j = 0; j < size; j++)
                mas[i][j] = mas[i][j]*5;
    [B]return ;[/B]
 
}[/I]
Вопрос такого рода: при перегрузке оператора, мы, очевидно, должны вернуть объект класса Matrix (эт вроде как по заданию) Что тогда следует возвращать в функции перегрузки?

Добавлено через 2 часа 11 минут
Ой, ошибся форумом. Администратор, перенесите пожалуйста в раздел С++
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.12.2012, 00:32     Перегрузка оператора *
Посмотрите здесь:

C++ Перегрузка оператора %
Перегрузка оператора = C++
Перегрузка оператора C++
C++ перегрузка оператора
C++ Перегрузка оператора
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
27.12.2012, 07:32     Перегрузка оператора * #2
Цитата Сообщение от Grinning liar Посмотреть сообщение
Что тогда следует возвращать в функции перегрузки?
Если тебе нужно изменить исходную матрицу, то можно вернуть *this. Только тогда логичнее заменить оператор * на *=.

C++
1
2
3
4
5
6
7
Matrix const Matrix::operator*= (float x) {
 
    for (int i = 0; i < size; i++)      
        for (int j = 0; j < size; j++)
                mas[i][j] = mas[i][j]*x;
    return *this;
}
После этого можно делать такой вызов: m1 *= 6; - элементы матрицы умножатся на 6.

Если нужно именно умножение, возвращающее результат, и не изменяющее исходный объект, то создай в функции новый объект и возвращай его.

C++
1
2
3
4
5
6
7
8
9
10
Matrix const Matrix::operator* (float x) const {
 
    Matrix res;
    res.size = size;
  
    for (int i = 0; i < size; i++)      
        for (int j = 0; j < size; j++)
                res.mas[i][j] = mas[i][j]*x;
    return res;
}
После этого можно вызывать: m2 = m1 * 6;

Только сделай нормальный конструктор, в котором будет выделяться память, и отдельно методы для ввода-вывода, а не группируй все в один метод create_mas.

Добавлено через 2 минуты
Цитата Сообщение от Grinning liar Посмотреть сообщение
float **mas = new float *[size];
Тут еще ошибка, создается локальная переменная mas, которая имеет просто одинаковое имя с элементом класса. Нужно:
C++
1
mas = new float *[size];
Grinning liar!
3 / 3 / 0
Регистрация: 01.11.2012
Сообщений: 38
27.12.2012, 21:26  [ТС]     Перегрузка оператора * #3
Благодарю, вроде заработало... Однако это я себе немного упростил условия там по заданию надо перегрузить еще =, и операции ввода-вывода. Как вообще это понять, не подскажете? У меня ведь и так по заданию выполняется
Matrix2=Matrix1*number.
Каким смыслом надо наделить это равно?

Полный текст задачи звучит так:
Реализовать класс Матрикс размерностью NxN, в котором хранятся числа float. Память под элементы выделять динамически. Перегрузить *, /, =. Перегрузить операции ввода-вывода в поток. В main'e привести примеры реализации класса Матрикс.
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
27.12.2012, 21:33     Перегрузка оператора * #4
У вас память под матрицу выделяется динамически, поэтому оператор = по умолчанию не подойдет. Он сделает только поверхностное копирование. То есть для элемента float **mas; - будет скопирован адрес, хранящийся в этом указателе. В итоге в обоих объектах будет указатель на одну и ту же область памяти.

Чтобы этого не произошло, переопределите свой оператор, где полностью скопируйте матрицу вручную.
Grinning liar!
3 / 3 / 0
Регистрация: 01.11.2012
Сообщений: 38
27.12.2012, 23:54  [ТС]     Перегрузка оператора * #5
Т.е. получается, что на данный момент, несмотря на то, что элементы умножаемой матрицы и конечной разные (и соответственно находятся в разных местах памяти), оба указателя хранят адрес начала исходной матрицы?
Grinning liar!
3 / 3 / 0
Регистрация: 01.11.2012
Сообщений: 38
30.12.2012, 00:13  [ТС]     Перегрузка оператора * #6
Цитата Сообщение от Schizorb Посмотреть сообщение

Чтобы этого не произошло, переопределите свой оператор, где полностью скопируйте матрицу вручную.
Т.е. копировать нужно только элементы матрицы без самого указателя, да?
Так будет правильно?

C++
1
2
3
4
5
6
7
8
Matrix &Matrix::operator= (const Matrix &m2){
    
    for (int i = 0; i < size; i++)      //заполняем массив числами
        for (int j = 0; j < size; j++)
            mas[i][j] = m2.mas[i][j];
    return *this;
 
}
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
30.12.2012, 07:58     Перегрузка оператора * #7
Цитата Сообщение от Grinning liar Посмотреть сообщение
Т.е. копировать нужно только элементы матрицы
Да, так. Только тут нужно будет следить, чтобы размеры обоих матриц совпадали. Иначе, если при
C++
1
m1 = m2;
у m1 размер был меньше, то произойдет ошибка, т.к. выделено недостаточно памяти. Можно, допустим, проверить размер, и если он не совпадает, то выделить память по новой
C++
1
2
3
delete [] mas;
size = m2.size;
mas = new int[size];
Еще в операторе присваивания нужна проверка на присваивание объекта самому себе:
C++
1
2
if(this == &mas2) // если адреса объектов справа и слева от = совпадают, значит это один и тот же объект
    return *this;
Добавлено через 3 минуты
Цитата Сообщение от Grinning liar Посмотреть сообщение
что элементы умножаемой матрицы и конечной разные (и соответственно находятся в разных местах памяти), оба указателя хранят адрес начала исходной матрицы?
Умножаемая и конечная матрица будут хранить разные указатели и разные элементы. Но если написать:
m1 = m2, то указатели mas в обоих этих объектах будут содержать один и тот же адрес. Так как выполнится m1.mas = m2.mas (а надо копировать поэлементно)
Grinning liar!
3 / 3 / 0
Регистрация: 01.11.2012
Сообщений: 38
30.12.2012, 19:39  [ТС]     Перегрузка оператора * #8
А разве нужна проверка на размерность? Мы ведь везде используем одно и то же входное значение size, которое задаем в первую очередь - матрицы ж не могут получиться разных размеров.
Спасибо за помощь!
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
30.12.2012, 19:51     Перегрузка оператора * #9
Цитата Сообщение от Grinning liar Посмотреть сообщение
матрицы ж не могут получиться разных размеров
Как не могут? Допустим, вы создали две матрицы (на самом деле для этого лучше сделайте конструктор с параметром-размер, вместо функции create_mas).

C++
1
2
m1.create_mas(5); 
m2.create_mas(10);
А потом присвоили m1 = m2; В m1 выделена память всего под 5 элементов, а в цикле (который у вас в перегруженном операторе) вы присваиваете аж 10 элементов.
Grinning liar!
3 / 3 / 0
Регистрация: 01.11.2012
Сообщений: 38
31.12.2012, 03:59  [ТС]     Перегрузка оператора * #10
И последний вопрос, если можно: пытаюсь описать деструктор класса, который высвобождает зарезервированную память после уничтожения объекта. Насколько я понял - когда уничтожить объект класса, компилятор понимает сам и вызывать деструктор (как и конструктор) в явном виде не надо. Описываю так, но при выполнении программы ошибит:
C++
1
2
3
4
5
6
Matrix::~Matrix() {
    
    for (int i = 0; i < size; i++) {
        delete [] mas[i];
    }
    delete [] mas;
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.12.2012, 07:04     Перегрузка оператора *
Еще ссылки по теме:

C++ Перегрузка оператора ++
Перегрузка оператора *= C++
C++ Перегрузка оператора ++

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

Или воспользуйтесь поиском по форуму:
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
31.12.2012, 07:04     Перегрузка оператора * #11
Цитата Сообщение от Grinning liar Посмотреть сообщение
в явном виде не надо
Да, явно не надо вызывать. В деструкторе не вижу ошибки. Может она есть в конструкторе или других методах, где память выдляется? Примерно так можно сделать конструктор с 1 параметром:
C++
1
2
3
4
5
6
7
8
9
10
11
12
Matrix::Matrix(int sz)
{
    size = sz;  // сохраняем размер
    
    mas = new float * [size];    //выделяем память на массив указателей начал строк массива
 
    for(int i = 0; i < size; i++)   //выделение памяти на каждую строку массива
    {
        mas[i] = new float [size];
    }
    
}
Yandex
Объявления
31.12.2012, 07:04     Перегрузка оператора *
Ответ Создать тему
Опции темы

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