初次学习C++,对于C++和编译的具体原理也不懂,模板类的使用的时候遇到了许多坑,在此记录以备日后查阅
关于C++模板函数使用的一点心得记录
类模板函数连接出问题
- 错误提示:
C:\Users\qsunj\AppData\Local\Temp\cc5VHYoh.o:main.cpp:(.text+0x12d): undefined reference to `Matrix<int>::operator+=(Matrix<int> const&)'
collect2.exe: error: ld returned 1 exit status
- 源码(
这里只详细贴出了出错部分的函数的信息,一些杂项被删去了):
//matrix.h
template <typename elemType>
class Matrix{
public:
/******************* constructor *********************/
//created a new matrix
Matrix( int rows, int columns )
: _rows( rows ), _cols( columns )
{
int size = _rows * _cols;
_matrix_data = new elemType[ size ];
for ( int ix=0; ix<size; ++ix ) {
_matrix_data[ ix ] = elemType();
}
}
//copy a matrix
Matrix( const Matrix &rhs )
{
_rows = rhs._rows;
_cols = rhs._cols;
int size = _rows * _cols;
_matrix_data = new elemType[ size ];
for ( int ix=0; ix<size; ++ix ) {
_matrix_data[ ix ] = rhs._matrix_data[ ix ];
}
}
/********** destructor <== Matrix(int,int) created static heap *********/
~Matrix() { delete [] _matrix_data; }
void print( const Matrix &rhs ) const
{
for (int row=0; row<_rows; row++) {
cout << "|\t";
for (int column=0; column<_cols; column++) {
cout << rhs( row, column) << '\t';
}
cout << '|' << endl;
}
}
int rows() const { return _rows; }
int cols() const { return _cols; }
Matrix& operator= ( const Matrix& );
void operator+= ( const Matrix& );
elemType& operator() ( int row, int column )
{ return _matrix_data[ row*cols() + column ]; }
const elemType& operator() ( int row, int column ) const
{ return _matrix_data[ row*cols() + column ]; }
bool is_same_size( const Matrix &m ) const
{ return rows()==m.rows() && cols()==m.cols(); }
private:
int _rows;
int _cols;
elemType *_matrix_data;
};
/**************************************************************************************
***************************************************************************************/
//matrix.cpp
template< typename elemType>
void Matrix<elemType>::operator+= ( const Matrix<elemType> &m )
{
if ( this.is_same_size(m) ) {
for ( int matrix_size=m.rows()*m.cols(), ix=0; ix<matrix_size; ix++ ) {
_matrix_data[ix] += m._matrix_data[ix];
}
}
}
/**************************************************************************************
***************************************************************************************/
//main.cpp
#include "pratice0602.h"
int main()
{
Matrix<int> m1(4, 4);
Matrix<int> m2(4, 4);
cout << "m1:" << endl;
m1.print( m1 );
cout << "m2:" << endl;
m1.print( m2 );
m1(0,0) = 1;
m1(3,3) = 1;
cout << "m1:" << endl;
m1.print( m1 );
m2 = m1;
m2 += m2;
cout << "m2:" << endl;
m1.print( m2 );
return 0;
}
原因及解决方法
- 解决方法:
1.将模板函数的实现写在类中
2.将实现函数的cpp文件一起包含在main.cpp中(例:#include “matrix.h”)个人比较倾向于方法1,方法2有时会出问题,也没仔细研究了
- 原因:
当一个模板不被用到的时侯它就不该被实例化出来;上面代码中编译main.cpp的时候用到了模板(在连接之前),但此时模板函数的定义在matrix.cpp中,而且两个文件是分开编译的,也就是说此时main.cpp想实现模板函数却找不到定义,自然报错“undefined reference to”(未定义)了。 - 更详细的说明进请看这位大佬
模板函数(template function)出现编译链接错误(link error)之解析
类模板友元函数出问题
- 错误提示:
In file included from main.cpp:1:
pratice0602.h:10:64: warning: friend declaration 'Matrix<elemType> operator+(const Matrix<elemType>&, const Matrix<elemType>&)' declares a non-template function [-Wnon-template-friend]
operator+ ( const Matrix<elemType>&, const Matrix<elemType>& );
^
pratice0602.h:10:64: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
C:\Users\qsunj\AppData\Local\Temp\cciEqvMa.o:main.cpp:(.text+0x134): undefined reference to `operator+(Matrix<int> const&, Matrix<int> const&)'
collect2.exe: error: ld returned 1 exit status
- 源码(
这里只详细贴出了出错部分的函数的信息,一些杂项被删去了):
//matrix.h
template <typename elemType>
class Matrix{
friend Matrix<elemType>
operator+ ( const Matrix<elemType>&, const Matrix<elemType>& );
public:
/******************* constructor *********************/
//created a new matrix
Matrix( int rows, int columns )
: _rows( rows ), _cols( columns )
{
int size = _rows * _cols;
_matrix_data = new elemType[ size ];
for ( int ix=0; ix<size; ++ix ) {
_matrix_data[ ix ] = elemType();
}
}
//copy a matrix
Matrix( const Matrix &rhs )
{
_rows = rhs._rows;
_cols = rhs._cols;
int size = _rows * _cols;
_matrix_data = new elemType[ size ];
for ( int ix=0; ix<size; ++ix ) {
_matrix_data[ ix ] = rhs._matrix_data[ ix ];
}
}
/********** destructor <== Matrix(int,int) created static heap *********/
~Matrix() { delete [] _matrix_data; }
void print( const Matrix &rhs ) const
{
for (int row=0; row<_rows; row++) {
cout << "|\t";
for (int column=0; column<_cols; column++) {
cout << rhs( row, column) << '\t';
}
cout << '|' << endl;
}
}
int rows() const { return _rows; }
int cols() const { return _cols; }
Matrix& operator= ( const Matrix& );
void operator+= ( const Matrix& );
elemType& operator() ( int row, int column )
{ return _matrix_data[ row*cols() + column ]; }
const elemType& operator() ( int row, int column ) const
{ return _matrix_data[ row*cols() + column ]; }
bool is_same_size( const Matrix &m ) const
{ return rows()==m.rows() && cols()==m.cols(); }
private:
int _rows;
int _cols;
elemType *_matrix_data;
};
template< typename elemType>
Matrix<elemType>& Matrix<elemType>::operator= ( const Matrix &m )
{
if ( this->_matrix_data != m._matrix_data ) {
_rows = m.rows();
_cols = m.cols();
int matrix_size = _rows*_cols;
delete [] _matrix_data;
_matrix_data = new elemType[ matrix_size ];
for ( int ix=0; ix<matrix_size; ix++ ) {
_matrix_data[ix] = m._matrix_data[ix];
}
}
return *this;
}
template< typename elemType>
void Matrix<elemType>::operator+= ( const Matrix<elemType> &m )
{
if ( rows()==m.rows() && cols()==m.cols() ) {
for ( int matrix_size=m.rows()*m.cols(), ix=0; ix<matrix_size; ix++ ) {
_matrix_data[ix] += m._matrix_data[ix];
}
}
}
template< typename elemType>
Matrix<elemType> operator+ ( const Matrix<elemType> &m1, const Matrix<elemType> &m2 )
{
Matrix<elemType> result( m1 );
result += m2;
return result;
}
/**************************************************************************************
***************************************************************************************/
//main.cpp
int main()
{
Matrix<int> m1(4, 4);
Matrix<int> m2(4, 4);
cout << "m1:" << endl;
m1.print( m1 );
cout << "m2:" << endl;
m1.print( m2 );
m1(0,0) = 1;
m1(3,3) = 1;
cout << "m1:" << endl;
m1.print( m1 );
m2 = m1;
m2 = m1 + m2;
cout << "m2:" << endl;
m1.print( m2 );
return 0;
}
原因及解决方法
- 解决方法(并非全部):
1.将模板友元函数的实现写在类中(下面是例子)
2.将模板友元函数的template与类的template显式的分开(下面是例子)friend Matrix<elemType> operator+ ( const Matrix<elemType>&, const Matrix<elemType>& ) { Matrix<elemType> result( m1 ); result += m2; return result; }
template< typename freType> friend Matrix<freType> operator+ ( const Matrix<freType>&, const Matrix<freType>& );
- 原因:
错误提示中提到"declares a non-template function"==>模板友元函数并没有被我所认为的那样被声明成了模板函数,由于我目前还不会用template< class T>这种模板,理解也不大行,具体原因请看大佬们的博客:模板类的友元函数
关于源码的来源:
- 环境:VSCode C++
- 源码来源: Essential C++联系题
- 简单的成功实现的源码:
//.h文件
#ifndef __PRATICE0602_H
#define __PRATICE0602_H
#include <iostream>
using namespace std;
template <typename elemType>
class Matrix{
template< typename freType>
friend Matrix<freType>
operator+ ( const Matrix<freType>&, const Matrix<freType>& );
friend Matrix<elemType>
operator* ( const Matrix<elemType>&m1, const Matrix<elemType>&m2 )
{
Matrix<elemType> result( m1.rows(), m2.cols());
for ( int ix=0; ix<4; ix++) {
for ( int jx=0; jx<4; jx++ ) {
result( ix, jx ) = 0;
for ( int kx=0; kx<4; kx++ )
result( ix, jx ) += m1(ix, kx) * m2(kx, jx);
}
}
return result;
}
public:
/******************* constructor *********************/
//created a new matrix
Matrix( int rows, int columns )
: _rows( rows ), _cols( columns )
{
int size = _rows * _cols;
_matrix_data = new elemType[ size ];
for ( int ix=0; ix<size; ++ix ) {
_matrix_data[ ix ] = elemType();
}
}
//copy a matrix
Matrix( const Matrix &rhs )
{
_rows = rhs._rows;
_cols = rhs._cols;
int size = _rows * _cols;
_matrix_data = new elemType[ size ];
for ( int ix=0; ix<size; ++ix ) {
_matrix_data[ ix ] = rhs._matrix_data[ ix ];
}
}
/********** destructor <== Matrix(int,int) created static heap *********/
~Matrix() { delete [] _matrix_data; }
void print( const Matrix &rhs ) const
{
for (int row=0; row<_rows; row++) {
cout << "|\t";
for (int column=0; column<_cols; column++) {
cout << rhs( row, column) << '\t';
}
cout << '|' << endl;
}
}
int rows() const { return _rows; }
int cols() const { return _cols; }
Matrix& operator= ( const Matrix& );
void operator+= ( const Matrix& );
elemType& operator() ( int row, int column )
{ return _matrix_data[ row*cols() + column ]; }
const elemType& operator() ( int row, int column ) const
{ return _matrix_data[ row*cols() + column ]; }
bool is_same_size( const Matrix &m ) const
{ return rows()==m.rows() && cols()==m.cols(); }
private:
int _rows;
int _cols;
elemType *_matrix_data;
};
template< typename elemType>
Matrix<elemType>& Matrix<elemType>::operator= ( const Matrix &m )
{
if ( this->_matrix_data != m._matrix_data ) {
_rows = m.rows();
_cols = m.cols();
int matrix_size = _rows*_cols;
delete [] _matrix_data;
_matrix_data = new elemType[ matrix_size ];
for ( int ix=0; ix<matrix_size; ix++ ) {
_matrix_data[ix] = m._matrix_data[ix];
}
}
return *this;
}
template< typename elemType>
void Matrix<elemType>::operator+= ( const Matrix<elemType> &m )
{
if ( rows()==m.rows() && cols()==m.cols() ) {
for ( int matrix_size=m.rows()*m.cols(), ix=0; ix<matrix_size; ix++ ) {
_matrix_data[ix] += m._matrix_data[ix];
}
}
}
template< typename elemType>
Matrix<elemType> operator+ ( const Matrix<elemType> &m1, const Matrix<elemType> &m2 )
{
Matrix<elemType> result( m1 );
result += m2;
return result;
}
#endif
/************************************************************************************************************************************************************************************/
//main.cpp文件
#include "pratice0602.h"
int main()
{
Matrix<int> m1(4, 4);
Matrix<int> m2(4, 4);
cout << "m1:" << endl;
m1.print( m1 );
cout << "m2:" << endl;
m1.print( m2 );
m1(0,0) = 1;
m1(3,3) = 1;
cout << "m1:" << endl;
m1.print( m1 );
m2 = m1 + m1;
cout << "m2 = m1 + m1:" << endl;
m1.print( m2 );
m2 = m2 * m2;
cout << "m2 * m2:" << endl;
m1.print( m2 );
cout << "pratice0602 is running OK!" << endl;
return 0;
}
如有错误请多指教