Sida 1 av 2

operator-problem i C++ [-- Löst! --]

Postat: 8 november 2006, 18:16:12
av arvidb
Jag har definierat en operator+ för en matrisklass som jag har skrivit, men kompilatorn klagar när jag försöker använda operatorn. Vad gör jag för fel?

Kod: Markera allt

my:~/cprog06/lab1ex12>g++ -Wall -o test matrix_test.cpp matrix.cpp ../lab14/vector.cpp
matrix_test.cpp: In function 'int main()':
matrix_test.cpp:41: error: no matching function for call to 'Matrix::Matrix(Matrix)'
matrix.h:16: note: candidates are: Matrix::Matrix(Matrix&)
Deklaration av operatorn (medlemsmetod i Matrix):

Kod: Markera allt

Matrix operator+(const Matrix &) const;
matrix_test.cpp:41:

Kod: Markera allt

std::cout << "m1 + m2: \n" << m1 + m2 << "\n";
operator+ tar ju en referens, så varför i hela friden vill kompilatorn ha en konstruktor, och dessutom prompt en copykonstruktor som tar ett objekt, och inte en referens?

Arvid

Postat: 8 november 2006, 18:35:20
av pheer
Eftersom den returnerar en Matrix, måste du inte definera operatorn << om du ska skriva ut den med cout? Men det kanske du redan har.

Postat: 8 november 2006, 18:38:08
av arvidb
Jodå, utskriftsoperatorn är definierad, implementerad och testad. :)

Arvid

Postat: 8 november 2006, 19:04:45
av pheer
Jag tror inte att den kan vara en medlemsfunktion. Följande fungerar.

Kod: Markera allt

#include <iostream>
using namespace std;

class test {
	friend ostream &operator<<(ostream &o, const test &t);

	private:
		int var;

	public:
		test(int val);
		int operator+(const test &b);
};

test::test(int val) {
	var = val;
}

int test::operator+(const test &b)  {
	return var+b.var;
}


ostream &operator<<(ostream &o, const test &t)  {
	cout << t.var;
	return o;
}

int main() {
	test a(3), b(2);

	cout << a+b;
}

Postat: 8 november 2006, 19:17:49
av arvidb
Nu förstår jag inte riktigt; test::operator+ är ju en medlemsfunktion i klassen test?

Jag har i vart fall testat att deklarera den som en icke-medlemsfunktion:

Kod: Markera allt

class Matrix
{
  ...
};

Matrix operator+(const Matrix &, const Matrix &);
men får exakt samma felmeddelande. Har även testat att anropa med

Kod: Markera allt

m1.operator+(m2)
- samma fel igen.

Arvid

Postat: 8 november 2006, 19:23:42
av pheer
Nä jag förstår inte heller hur jag tänkte :wacko:
Om du postar lite mer kod kanske det blir lättare att se ev. fel.

Postat: 8 november 2006, 19:27:38
av arvidb
Det kanske är bäst att klippa in lite mer av koden:

Ur matrix_test.cpp:

Kod: Markera allt

#include <iostream>
#include "matrix.h"

int main()
{

    ...

    Matrix m1(5, 5);
    // Fyll i data
    for (int i = 0; i < m1.getrows(); ++i)
      for (int j = 0; j < m1.getcols(); ++j)
        m1[i][j] = i*m1.getcols() + j;
    
    Matrix m2(5, 5);
    // Fyll i data
    for (int i = 0; i < m2.getrows(); ++i)
      for (int j = 0; j < m2.getcols(); ++j)
        m2[i][j] = 1;
    
    std::cout << "m1: \n" << m1 << "\n";
    std::cout << "m1.transpose(): \n" << m1.transpose() << "\n";
    std::cout << "m1 + m2: \n" << m1 + m2 << "\n";  // Kompileringsfel

    return 0;
}
matrix.h:

Kod: Markera allt

#ifndef MATRIX_H
#define MATRIX_H

#include <iostream>
#include "../lab14/vector.h"

class Matrix 
{
private:
  int m_, n_; // Rows (m) and columns (n) of matrix
  Vector **row;
protected:
  void check_bounds(int m, int n) const;
public:
  Matrix(int m, int n);
  Matrix(Matrix &ref);
  virtual ~Matrix();

  int getrows() const { return (m_); }
  int getcols() const { return (n_); }
  
  Matrix &operator=(const Matrix &);
  Vector &operator[](int m);
  const Vector operator[](int m) const;
  
/* Lab 1.3 - Matrix arithmetics */
  Matrix &identity();
  Matrix &transpose();

  Matrix operator+(const Matrix &) const;
  Matrix operator-(const Matrix &) const;
  Matrix operator*(const Matrix &) const;
  Matrix operator*(const int) const;
  
  Matrix operator-() const;    // Unary negation

};

std::ostream &operator<<(std::ostream &os, const Matrix &matrix);

#endif
och implementationen av operator+ (i matrix.cpp):

Kod: Markera allt

Matrix Matrix::operator+(const Matrix &ref) const
{
  if ((m_ != ref.m_) || (n_ != ref.n_))
    throw "Matrix::operator+(const Matrix &): Matrix dimensions must be equal.";

  Matrix temp(m_, n_);

  for (int i = 0; i < m_; ++i)
    for (int j = 0; j < n_; ++j)
      temp[i][j] = (*row[i])[j] + ref[i][j];
        
  return (temp);
}
Edit: det ska nämnas att de andra Matrix-operatorerna ger upphov till samma fel - ingen funkar, förutom = och [].

Arvid

Postat: 8 november 2006, 19:46:15
av pheer
Följande kompilerar utan fel för mig (Visual C++ toolkit 2003).

Kod: Markera allt

#include <iostream> 
#include "matrix.h" 

int main() 
{ 


    Matrix m1(5, 5); 

    Matrix m2(5, 5); 

    std::cout << "m1 + m2: \n" << m1 +m2 << "\n";  // Kompileringsfel 

    return 0; 
}

Kod: Markera allt

#ifndef MATRIX_H 
#define MATRIX_H 

#include <iostream> 
//#include "../lab14/vector.h" 

class Matrix 
{ 
	private: 
		int m_, n_; // Rows (m) and columns (n) of matrix 

	public: 
		Matrix(int m, int n); 


		Matrix operator+(const Matrix &) const; 


}; 

std::ostream &operator<<(std::ostream &os, const Matrix &matrix); 

#endif

Kod: Markera allt

#include "matrix.h"

Matrix::Matrix(int m, int n) {

}

Matrix Matrix::operator+(const Matrix &ref) const 
{ 
	Matrix temp(m_, n_); 

	return (temp); 
}

std::ostream &operator<<(std::ostream &os, const Matrix &matrix) {
	return os;
}

Postat: 8 november 2006, 19:59:40
av arvidb
Jo, det kompilerar fint för mig också, och även så om jag lägger till en tom copy-konstruktor Matrix(const Matrix &).

Vad sjutton är skillnaden?

:?: :humm:

Arvid

Postat: 8 november 2006, 20:11:28
av simon78
Nu har jag inte läst hela tråden men för att svara på OP.

Kod: Markera allt

 Matrix Matrix::operator+(const Matrix &ref) const
{
  if ((m_ != ref.m_) || (n_ != ref.n_))
    throw "Matrix::operator+(const Matrix &): Matrix dimensions must be equal.";

  Matrix temp(m_, n_); <--- Här vill den ha konstructorn

  for (int i = 0; i < m_; ++i)
    for (int j = 0; j < n_; ++j)
      temp[i][j] = (*row[i])[j] + ref[i][j];
       
  return (temp); <--- här copy-konstructorn

Postat: 8 november 2006, 20:38:25
av arvidb
simon78: Deklarerar jag copy-konstructorn explicit så får jag kompileringsfel även där du visar, ja. (Observera att det finns en copy-konstruktor i klassen Matrix.)

Kolla på felet igen - kompilatorn vill ha en Matrix::Matrix(Matrix) (d.v.s. en som tar Matrix istf Matrix-referens som parameter).

Arvid

Postat: 8 november 2006, 21:04:58
av Abra Hana
*
Hur ser implimentation av dessa två klasser ?

public:
Matrix(int m, int n);
Matrix(Matrix &ref);

Dessa är inga standard konstruktorer , bör implimenteras .

*

Postat: 8 november 2006, 21:09:24
av arvidb
Implementationerna av metoderna ser ut så här:

Kod: Markera allt

Matrix::Matrix(int m, int n) : m_(m), n_(n)
{
  row = new Vector *[m_];
  for (int i = 0; i < m_; ++i)
    row[i] = new Vector(n_);
}

Matrix::Matrix(Matrix &ref) : m_(ref.m_), n_(ref.n_)
{
  row = new Vector *[m_];
  for (int i = 0; i < m_; ++i)
    row[i] = new Vector(n_); 
}
Copy-konstruktorn Matrix(Matrix &ref); är väl standard? Men eftersom jag har deklarerat den så implementerar jag den ju såklart också.

Arvid

Postat: 8 november 2006, 21:47:50
av Abra Hana
*

Jag ser inget samband mellan dessa :

// Här , du deklarerar och initierar en enkel objekt m1 av klassen Matrix .

Matrix m1(5,5)

// och här betraktar du denna objektet m1 som en array av klassen Matrix

m1[j] = i*m1.getcols() + j;

Du skapar en en enda Matrix objekt , men du försöker initiera inte mindre
än 25 matrix objekter när loopet har kört färdigt . Var kommer ifrån alla
andra 24 Matrix objekter ? .

Du gör samma sak för m2 !

*

Postat: 8 november 2006, 22:13:15
av arvidb
Matrix har ju operator[] deklarerad:

Kod: Markera allt

Vector &operator[](int m);
Vector i sin tur har också en operator[].

Dessutom är resultatet av uttrycket "i*m1.getcols() + j;" av typen int, och Matrix har ingen implicit konstruktor som tar en int som parameter - det går alltså inte att initiera en Matrix på det sättet.

Inget fel där alltså, så vitt jag kan se. En utskrift av m1 eller m2 visar också att det fungerar som avsett, nämligen att matrisens element tilldelas.

Arvid