Консультация № 191664
04.11.2017, 15:23
0.00 руб.
0 8 0
Уважаемые эксперты! В очередной раз прошу Вас помочь мне с освоением С++.
У меня такая задача: умножить матрицу на вектор. Тремя разными способами: через статические массивы, через указатели и с использованием индексов.
Делаю два класса "вектор" и "матрица". Хочу концептуально сделать наиболее красиво, но силу своих возможностей, которые у меня на начальном уровне .
Посоветуйте какой выбрать вариант:
1. сделать базовый класс вектор, производный матрица
2. базовый матрица - производный вектор
3. не связываться с наследованием и сделать с помощью дружественных функций или один класс сделать классом-другом второму в целом?
Хочу сделать именно через классы, так как все таки это ООП.

Обсуждение

давно
Посетитель
401172
78
05.11.2017, 19:35
общий
Выходные заканчиваются, надеюсь мне кто-то ответит
Решила использовать третий вариант, т.е. сделала два класса Vector и Matrix + объявила Vector другом классу Matrix.
Сделала первый способ со статическими массивами, работаю над вторым - использование динамических массивов.
Возникла следующая проблема: не выводятся массивы на экран (ни вектор, ни матрица), т.е. успешно производится сборка проекта, а затем программа доходит до функции вывода на экран и зависает.
Привожу код объявления класса Vector:
Код:
#pragma once
#include "Matrix.h"

class Vector
{
public:
Vector(Matrix&); // конструктор
~Vector(); // деструктор
void ShowVector(); // вывод вектора на экран
private:
int *vector; // указатель на целочисленный массив
int SizeVector; // размер вектора
};

Ниже код реализации функций этого же класса:
Код:
#include "stdafx.h"
#include "Vector.h"
#include "Matrix.h"
#include <iostream>
using namespace std;

Vector::Vector(Matrix& m)
{
SizeVector = m.ColumnsMatrix;
// объявление одномерного динамического массива
int *vector = new int[SizeVector];
cout << "Enter elements of vector: " << endl;
// заполнение вектора
for (int i = 0; i < SizeVector; i++)
{
cout << "vector[" << (i + 1) << "] = ";
cin >> *(vector + i);
}
}

Vector::~Vector()
{
cout << "Release memory allocated for the vector!" << endl;
free(vector);
}

void Vector::ShowVector()
{
cout << "The introduced vector: " << endl;
for (int i = 0; i < SizeVector; i++)
{
cout << *(vector + i) << endl;
}
}


Использовать можно только указатели, их явное разыменывание.
Код класса Matrix приводить пока не буду, сдается мне, что это одна и та же ошибка...
давно
Старший Модератор
312929
1973
08.11.2017, 03:03
общий
08.11.2017, 14:39
Адресаты:
Несколько замечаний к Вашему коду:

1. Делать ввод данных с экрана прямо в конструкторе не есть хорошо: конструктор предназначен не для этого, а для выделения памяти под объект и его инициализации из другого объекта.

2. Использовать в конструкторе класса Vector объект класса Matrix только для передачи из него размера вектора излишне, достаточно передать конструктору сам размер.

3. Выводить вектор на экран отдельным методом нормально, но обычно для этих целей перегружают операторы потокового ввода-вывода класса iostream.

4. Освобождать память через free допустимо, но стандартно для этого используют delete.

Исходя из вышесказанного, класс Vector можно объявить так:
[code lang=php]#include "iostream.h"

class Vector
{
public:
Vector(unsigned int); // конструктор
~Vector(); // деструктор
friend istream& operator>>(istream&, Vector&);
friend ostream& operator<<(ostream&, const Vector&);
private:
int *vector; // указатель на целочисленный массив
unsigned int SizeVector; // размер вектора
};[/code]
и реализовать так:
[code lang=php]#include "Vector.h"

Vector::Vector(unsigned int n)
{
// объявление одномерного динамического массива
vector = new int[SizeVector=n];
}

Vector::~Vector()
{
cout << "Release memory allocated for the vector!" << endl;
delete [] vector;
}

istream& operator>>(istream &is, Vector &v)
{
cout << "Enter " << v.SizeVector << " elements of vector: ";
// заполнение вектора
for (int i = 0; i < v.SizeVector; i++)
{
cin >> *(v.vector + i);
}
}

ostream& operator<<(ostream &os, const Vector &v)
{
cout << "The introduced vector: ";
for (int i = 0; i < v.SizeVector; i++)
{
cout << *(v.vector + i) << " ";
}
cout << endl;
}[/code]
Тогда работа с классом будет выглядеть очень просто, например:
[code lang=php]Vector v(5); // объявляем вектор из 5 элементов
cin >> v; // вводим элементы вектора
cout << v; // выводим элементы вектора[/code]
давно
Посетитель
401172
78
09.11.2017, 13:19
общий
Цитата: Коцюрбенко Алексей Владимирович
1. Делать ввод данных с экрана прямо в конструкторе не есть хорошо: конструктор предназначен не для этого, а для выделения памяти под объект и его инициализации из другого объекта.


Надо было сразу сказать (сорри ), что по условию задачи необходимо соблюсти определенную последовательность.
1. пользователь должен в main создать объект класса матрица не передавая никаких аргументов, ответить на два вопроса: сколько количество строк и столбцов в матрице.
2. пользователь должен создать объект класса вектор, после чего должен появится запрос от программы о заполнении элементов вектора (без уточнения его размера, размер автоматически должен быть определен как количество столбцов в матрице).
Цитата: Коцюрбенко Алексей Владимирович
2. Использовать в конструкторе класса Vector объект класса Matrix только для передачи из него размера вектора излишне, достаточно передать конструктору сам размер.

Поэтому мне пришлось передавать в конструктор вектора в качестве параметра созданный объект класса матрица.
3. после того как вектор заполнен, пользователь должен вызвать методы вывода матрицы и вектора на экран.
4. пользователь должен вызвать функцию умножения с выводом на экран результата.
5. пользователь должен вызвать функцию поиска максимального значения.

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

Цитата: Коцюрбенко Алексей Владимирович
4. Освобождать память через free допустимо, но стандартно для этого используют delete.

Полностью согласна, не знаю, что на меня нашло)))
Сейчас это выглядит так:
Код:
delete [] vector;
vector = nulptr; // надо ли добавить такую строчку?


Цитата: Коцюрбенко Алексей Владимирович
3. Выводить вектор на экран отдельным методом нормально, но обычно для этих целей перегружают операторы потокового ввода-вывода класса iostream.

Спасибо за совет, это мне надо осмыслить, поскольку в перегрузке операторов я еще не очень...
давно
Посетитель
401172
78
09.11.2017, 13:31
общий
4 и 5 пункт я реализовала уже, поэтому не стала код выкладывать.....
давно
Посетитель
401172
78
09.11.2017, 14:02
общий
Насколько я поняла, так
Код:
Vector v(5); // объявляем вектор из 5 элементов 
нельзя создать вектор, потому как пользователь может ошибочно ввести число элементов, которое не соответствует числу столбцов в матрице.
То есть придется писать в руководстве пользователя что-то такое: "при создании объекта класса вектор количество элементов должно совпадать с количеством столбцов в матрице, на которую вектор планируется перемножить".
Плюс прописывать проверку на выполнение этого условия опять же в конструкторе:
Код:
if(int x != количество столбцов матрицы) { cout << "Error" << endl; }
, что все равно влечет за собой передачу объекта матрицы по ссылке в качестве аргумента.
давно
Старший Модератор
312929
1973
09.11.2017, 15:59
общий
Адресаты:
Тогда действительно для класса Vector потребуется конструктор Vector(Matrix&). Что касается перегрузки операторов ввода-вывода, то для вектора я пример уже привёл, а для матрицы объявление будет таким же:
Код:

friend istream& operator>>(istream&, Matrix&);
friend ostream& operator<<(ostream&, const Matrix&);

а реализация немного сложнее (на один цикл больше):
Код:

istream& operator>>(istream &is, Matrix &m)
{
cout << "Enter matrix (" << m.RowsMatirx << "x" << m.ColumnsMatrix << "):" << endl;
for (int i=0; i<m.RowsMatrix; i++)
for (int j=0; j<m.ColumnsMatirx; j++)
cin >> *(*(m.matrix+i)+j);
}

ostream& operator<<(ostream &os, const Matrix &m)
{
cout << "The introduced matrix: " << endl;
for (int i=0; i<m.RowsMatirx; i++)
{
for (int j=0; j<m.ColumnsMatrix; j++)
cout << *(*(m.matrix+i)+j) << " ";
cout << endl;
}
}
давно
Посетитель
401172
78
09.11.2017, 20:55
общий
Спасибо за ответ! Все понятно
давно
Мастер-Эксперт
425
4118
12.11.2017, 09:41
общий
Адресаты:
Цитата: pNod
1. пользователь должен в main создать объект класса матрица не передавая никаких аргументов, ответить на два вопроса: сколько количество строк и столбцов в матрице.

Дык и в этом случае в конструкторе нет никакой необходимости вопрошать с экрана чего-либо - можно сделать метод, который присваивает данные полям класса и на этой основе выделяет память под объект.
А ввод данных (вместе с вопросами), как и написано в задании, будет в main...
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Форма ответа