[완료]c++에서 <<연산자 overriding시 컴파일 에러 문제
글쓴이: sawa500 / 작성시간: 화, 2007/06/05 - 8:18오전
C++로 행렬 class를 만들고 있는데 namespace 부분을 주석처리하면 이상없이 컴파일이 되다가도 주석을 해제하고 컴파일시키면 아래 메시지와 같은 에러를 내뱉고 있습니다. 무슨 이유로 이러는지 아래 코드를 보시고 해결방법을 아시는 분이 계시면 가르쳐주시면 감사하겠습니다. 덤으로 mat_test파일에서 C=A+B; cout << C << endl;로 하지 않고 cout << A+B << endl을 직접쓰면 에러가 나는 이유도 가르쳐 주시면 고맙겠습니다.
요약하자면
1. namespace를 적용하기전엔 compile이 되던 코드가 namespace를 적용시키면 compile에러를 내는 이유와 해결방법
2. 연산자 오버로딩을 이용하여 행렬 연산을 C=A+B; cout << C << endl;말고 직접 cout << A+B << endl;을 사용하면 에러가 나는 이유와 해결방법 => 해결되었음.
입니다.
mat_test.o(.text+0x28e): In function `main': d:/MyProjects/C++/ebm/mat_test.cpp:13: undefined reference to `EBM::operator<<(std::ostream&, EBM::Matrix&)' mat_test.o(.text+0x2bc):d:/MyProjects/C++/ebm/mat_test.cpp:15: undefined reference to `EBM::operator<<(std::ostream&, EBM::Matrix&)' mat_test.o(.text+0x403):d:/MyProjects/C++/ebm/mat_test.cpp:20: undefined reference to `EBM::operator<<(std::ostream&, EBM::Matrix&)' mat_test.o(.text+0x537):d:/MyProjects/C++/ebm/mat_test.cpp:22: undefined reference to `EBM::operator<<(std::ostream&, EBM::Matrix&)' mat_test.o(.text+0x70b):d:/MyProjects/C++/ebm/mat_test.cpp:24: undefined reference to `EBM::operator<<(std::ostream&, EBM::Matrix&)'
mat.h 파일 내용
#ifndef __MAT_H #define __MAT_H #include <vector> #include <string> #include <iostream> using namespace std; //namespace EBM //{ class Matrix { public: Matrix(); Matrix(size_t rows, size_t cols, double value=0.0); ~Matrix(); //copy constructor Matrix(const Matrix& s); public: void resize(size_t rows, size_t cols); void identity(size_t mn); void identity(); // if rows is not equal cols, then matrix is reduced to square matrix sized by min(rows,cols) void print(); void assign(size_t row, size_t col, double value); void trans(); // exchange row and col public: inline size_t rows() { return this->m; }; inline size_t cols() { return this->n; }; public: //operation Matrix operator+(Matrix B); Matrix operator-(Matrix B); Matrix operator*(Matrix B); // vector<double>& operator[](size_t m); friend ostream& operator<<(ostream& os, Matrix& mat); //assign operator const Matrix& operator=(const Matrix& rhs); private: vector<double>* v; // row vector size_t m; size_t n; }; //} #endif /* __MAT_H */
mat.cpp파일 내용
#include "mat.h" //using namespace EBM; Matrix::Matrix() { this->m = 0; this->n = 0; this->v = NULL; } Matrix::Matrix(size_t rows, size_t cols, double value) { this->m = rows; this->n = cols; this->v = new vector<double>[rows]; for(size_t i=0; i<this->m; i++) { this->v[i].resize(n,value); } } Matrix::~Matrix() { this->m = 0; this->n = 0; delete[] this->v; } //copy constructor Matrix::Matrix(const Matrix& s) { this->m = s.m; this->n = s.n; this->v = new vector<double>[s.m]; for(size_t i=0; i<this->m; i++) { this->v[i].resize(n); for(size_t j=0; j<this->n; j++) { this->v[i][j] = s.v[i][j]; } } } //assign operator const Matrix& Matrix::operator=(const Matrix& rhs) { if (this != &rhs) { // 오른쪽의 인자가 자기자신이 아닐 경우만 진행한다. delete[] this->v; // 필요없는 메모리를 반납한다. this->v = new vector<double>[rhs.m]; // 새로운 메모리를 할당한다. this->m = rhs.m; this->n = rhs.n; for(size_t i=0; i<this->m; i++) { this->v[i].resize(n,0.0); for(size_t j=0; j<this->n; j++) { this->v[i][j] = rhs.v[i][j]; } } } return *this; // 자기자신의 레퍼런스를 반환한다. 이제 따로 떨어진 대입결과가 동작할 것이다. } void Matrix::resize(size_t rows, size_t cols) { delete[] this->v; this->m = rows; this->n = cols; this->v = new vector<double>[rows]; for(size_t i=0; i<this->m; i++) { this->v[i].resize(n,0.0); } } void Matrix::identity(size_t mn) { delete[] this->v; this->m = mn; this->n = mn; this->v = new vector<double>[mn]; for(size_t i=0; i<this->m; i++) { this->v[i].resize(mn,0.0); for(size_t j=0; j<this->n; j++) { if(i==j) { this->v[i][j] = 1.0; } } } } void Matrix::identity() { delete[] this->v; size_t m; m = this->m<=this->n?this->m:this->n; this->m = m; this->n = m; this->v = new vector<double>[m]; for(size_t i=0; i<this->m; i++) { this->v[i].resize(m,0.0); for(size_t j=0; j<this->n; j++) { if(i==j) { this->v[i][j] = 1.0; } } } } vector<double>& Matrix::operator[](size_t m) { return this->v[m]; } ostream& operator<<(ostream& os, Matrix& obj) { size_t m = obj.rows(); size_t n = obj.cols(); os << m << " x " << n << endl; for(size_t i=0; i<m; i++) { os << "[ "; for(size_t j=0; j<n; j++) { os << obj[i][j]; if(j<n-1) { os << " "; } } os << " ] " << endl; } return os; } void Matrix::print() { cout << this->m << " x " << this->n << endl; for(size_t i=0; i<this->m; i++) { cout << "[ "; for(size_t j=0; j<this->n; j++) { cout << this->v[i][j]; if(j<this->n-1) { cout << " "; } } cout << " ] " << endl; } } Matrix Matrix::operator+(Matrix B) { Matrix C(this->m,this->n, 0.0); for(size_t i=0; i<this->m; i++) { for(size_t j=0; j<this->n; j++) { C.v[i][j] = this->v[i][j] + B.v[i][j]; } } return C; } Matrix Matrix::operator-(Matrix B) { Matrix C(this->m, this->n, 0.0); for(size_t i=0; i<this->m; i++) { for(size_t j=0; j<this->n; j++) { C.v[i][j] = this->v[i][j] - B.v[i][j]; } } return C; } Matrix Matrix::operator*(Matrix B) { Matrix C(this->m, B.n, 0.0); for(size_t i=0; i<this->m; i++) { for(size_t j=0; j<B.n; j++) { for(size_t k=0; k<this->n; k++) { C.v[i][j] = C.v[i][j] + this->v[i][k]*B.v[k][j]; } } } return C; } void Matrix::assign(size_t row, size_t col, double value) { this->v[row][col] = value; } void Matrix::trans() { Matrix T(this->n, this->m, 0.0); for(size_t i=0; i<this->m; i++) { for(size_t j=0; j<this->n; j++) { T[j][i] = this->v[i][j]; } } this->m = T.m; this->n = T.n; *this = T; }
mat_test.cpp 파일 내용
#include "mat.h" //using namespace EBM; int main() { Matrix A(2,2); Matrix B(2,2,3.0); Matrix C; vector<double> v; A[0][1] = 100; A[1][0] = 200; C = A+B; cout << "A+B = "<< endl << A+B << endl; C = A-B; cout << "A-B = "<< endl << C << endl; C = A*B; cout << "A*B = "<< endl << C << endl; return 0; }
Forums:
제 기억이 맞는지 모르겠지만..
ostream& 나 istream&의 연산자 오버로딩은
헤더파일안에서 해야되는게 아닌가 싶은데요..
아닌가요? ;; 기억이 가물가물
1. friend ostream&
1.
friend ostream& operator<<(ostream& os, Matrix &obj);
=> friend ostream& operator<<(ostream& os, Matrix obj); (1)
=> friend ostream& operator<<(ostream& os, const Matrix &obj); (2)
(1)의 내용대로 하면 바로 컴파일 될것이라 판단됩니다.
(2)의 내용처럼 한다면 몇개의 멤버함수를 const 처리 해야 합니다.
2.
const Matrix& operator=(const Matrix& rhs);
=> Matrix& operator=(const Matrix& rhs);
대입연산자의 원형은 아래것이 맞습니다.
위에처럼 한다면 다음과 같은 식이 위배됩니다.
a = b = c;
--
cdecl
--
cdecl
namespace 문제.
cdecl님께서 알려주신 대로 바꾸니 cout << A+B << endl; 문제가 바로 해결되었습니다.
헌데 namespace EBM에 쳐진 주석을 해제하고 컴파일 해보면
undefined reference to `EBM::operator<<(std::ostream&, EBM::Matrix)
이라는 에러메시지를 보내는데 왜 못찾겠다는 건지 모르겠습니다.
namespace 문제
자문자답이 되어버렸네요.
namespace를 쓸때 헤더파일과 소스파일에 둘다 namespace 블록으로 묶어주어야하는 걸 모르고 소스파일에다가는 using namespace를 사용해서 생긴 에러였습니다.
도움주신 분들 모두 감사합니다.
declaration과 definition은 동일한 namespace에 넣으세요
mat.cpp에 있는 Matrix의 definition이, declaration과 동일한 namespace에 존재하지 않아서 그런 것 같습니다.
mat.cpp에서,
using namespace EBM;
를 사용하는 대신,
mat.cpp의 Matrix의 definition들을 namespace EBM { }에 넣어주시면 잘 될 겁니다.
댓글 달기