Вывод двойного указателя на объект с оператором вставки перегруженного потока?

В настоящее время я реализую класс, который может представлять матрицы с использованием динамических массивов с двойными указателями (типа double), перегружены */-/+ operators для матричной арифметики и оператора вставки перегруженного потока для вывода матриц.

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

Мое определение класса:

class clMatrix {
  private:
    int rows, cols ;
    double **arr ;
  public:
    clMatrix() ;
    ~clMatrix() ;
    void userInput(char matrixId, int &rowN, int &colN) ;
    friend ostream &operator<<(ostream& os, const clMatrix*&) ;
    friend clMatrix &operator+(const clMatrix&, const clMatrix&) ;
    friend clMatrix &operator-(const clMatrix&, const clMatrix&) ;
    friend clMatrix &operator*(const clMatrix&, const clMatrix&) ;
} ;

Мои определения функций класса (в частности, ввод и вывод, как арифметические операторы, которые я даже не проверял, так как мне не хватает вывода для тестирования) и main:

Функция выхода:

ostream& operator<<(ostream& os, const clMatrix *&printMatrix) {
  for(int i = 0; i < printMatrix->rows; ++i) {
    os << "\nRow " << i+1 << ": " ;
    for(int j = 0; j < printMatrix->cols; ++j) {
      os << printMatrix->arr[i][j] << " " ;
    }
  }
  os << endl ;
  return os ;
}

Функция ввода:

void clMatrix::userInput(char matrixId, int &rowN, int &colN) {
  string in ;
  int idx, rowLen, colLen ;
  double rowarr[50] ;
  bool firstRow = 1 ;
  colLen = 0 ;
  rowLen = 0 ;
  idx = 0 ;
  cout << "Matrix: " << "'" << matrixId << "'" << endl ;
  cout << "Enter row 1: " ;
  getline(cin,in) ;
  while(in != "") {
    ++rowLen ;
    stringstream iss(initial) ;
    while(iss >> rowarr[idx]) {
      ++idx ;
    }
    if(firstRow) {
      colLen = idx ;
      firstRow = 0 ;
    }
    cout << "Enter row " << rowLen + 1 << ": " ;
    getline(cin,in) ;
  }
  idx = 0 ;
  rows = rowLen ;
  cols = colLen ;

  arr  = new double*[rows] ;
  for(int i = 0; i < rows; ++i) {
    arr[i] = new double[cols] ;
  }
  idx = 0 ;
  for(int i = 0; i < rows; ++i) {
    for(int j = 0; j < cols; ++j) {
      arr[i][j] = rowarr[idx] ;
      ++idx ;
    }
  }
}

Основная функция:

#ifndef HEADER_H
#define HEADER_H
#include "header.h"
int main() {
  clMatrix *aMatrix ;
  clMatrix *bMatrix ;
  aMatrix = new clMatrix ;
  bMatrix = new clMatrix ;
  char matrixId ;
  int rowsA, rowsB, colsA, colsB ;

  matrixId = 'A' ;
  cout << "Matrix A input:\n" ;
  aMatrix->userInput(matrixId,rowsA,colsA) ;

  matrixId = 'B' ;
  cout << "Matrix B input:\n" ;
  bMatrix->userInput(matrixId,rowsB,colsB) ;

  cout << "Matrix A output:\n" ;
  cout << aMatrix ;
  cout << "Matrix B output:\n" ;
  cout << bMatrix ;

  delete aMatrix ;
  delete bMatrix ;
  return 0 ;
}

Когда я запускаю программу, я получаю один, выделенный кучей адрес для каждой матрицы, и я думаю, что они отключены на 32 бита? (Мой самый последний прогон: 0x1dbcc20 и 0x1dbcc40). Означает ли это, что только две мои целочисленные переменные-члены выделяются для 16 битов каждая? Если это так, то мое распределение памяти неправильное? Я также попробовал почти все возможные градации разыменования двойного указателя двойного типа, но безрезультатно. Также, как ни странно, строка:

os << "\nRow " << i+1 << ": " ;

из моей функции перегрузки вставки потока никогда не печатается на консоль, несмотря на то, что она предназначена для печати для каждой строки, но программа пропускает ее во внутреннюю часть цикла и печатает этот чертов адрес. Я просто не понимаю.

У меня закончились опции (я редактировал / перекомпилировал / запустил и отлаживал в GDB/valgrind в течение последних 5 часов), исчерпал практически все ресурсы, которые я мог найти относящиеся к моей проблеме, и поэтому теперь в 2:45 утра, ужасно лишенный сна, я обращаюсь к вам, храбрым душам ТАК. Любая помощь с благодарностью, спасибо! (Извините, если это бессвязно и трудно понять, я очень устал!)

2 ответа

Решение

У вашего оператора потока есть второй формальный параметр const clMatrix *&printMatrix, Это lvalue ссылка на константный указатель на clMatrix, Вы вызываете это с неконстантным указателем lvalue на clMatrix, которая не будет привязана к ссылке (если она есть, вы можете использовать ее для нарушения безопасности const).

В результате единственной доступной перегрузкой является ostream функция-член operator<<(const void* value), который печатает необработанное значение указателя.

Любая из следующих подписей будет работать:

operator<<(ostream&, const clMatrix*const &)
operator<<(ostream&, const clMatrix*)

Но было бы более идиоматичным взять clMatrix параметр напрямую по константной ссылке:

operator<<(ostream&, const clMatrix&)

Ваш перегруженный оператор называется? const clMatrix*& кажется странным Из-за этого компилятор выбирает встроенный operator<<, Передайте просто const-ссылку на clMatrix, И называть это cout << *aMatrix, Если вы сделаете это, компилятор не перепутает вашу перегрузку с build-it operator<<,

Ваш код выглядит правильно, но довольно сложно. Я бы использовал один std::vector или же std::valarray хранить все значения M*N и обращаться к элементу, используя arr[n*cols+m], Позвольте пользователю заранее указать количество строк и столбцов, выделить достаточно памяти и заполнить его std::cout >> arr[i*cols+j], перегрузка operator>> для входного потока и вашей матрицы вместо userInput функция.

Другие вопросы по тегам