C++基础问题(*this,及const引用)

fietiger 2009-04-20 01:54:22
最近在做一个矩阵的类,
class CXMref;
class CXMatrix
{

public:
friend class CMO ;
// construction and destruction
CXMatrix() ; // default constructor
CXMatrix(double val);
CXMatrix(int nRowsH, int nCols,double* pData) ; // constructs an empty matrix of this size
CXMatrix(const CXMatrix &other) ; // copy constructor
CXMatrix(int nRowsH, int nCols =1) ; // constructs an empty matrix of this size
Null();
virtual ~CXMatrix(); // destructor
CXMref GetElement(int nRowsH, int nCol) const;

CXMref GetElement(int nPos) const;
bool shared () { return (m_pMat->GetRef() > 1); }
inline int GetNumColumns() const { return m_NumColumns ; } ;
inline int GetNumRows() const { return m_NumRowsH ; } ;
inline int size() const { return m_NumColumns *m_NumRowsH; } ;
void clone ();



CXMatrix operator +(const CXMatrix& mat2) const;
CXMatrix operator -(const CXMatrix& mat2) const;
CXMatrix operator *(const CXMatrix& mat2) const;
CXMatrix operator /(const CXMatrix& mat2) const;


CXMatrix operator +(const double& mat2) const;
CXMatrix operator -(const double& mat2) const;
CXMatrix operator *(const double& mat2) const;
CXMatrix operator /(const double& mat2) const;

CXMatrix operator !() const;
CXMatrix operator ~() const;
CXMatrix operator -() const;

CXMatrix& operator = (const CXMatrix &other) ;

CXMatrix& operator += (const CXMatrix& mat2) ;
CXMatrix& operator -= (const CXMatrix& mat2) ;
CXMatrix& operator *= (const CXMatrix &other) ;
CXMatrix& operator /= (const CXMatrix& mat2) ;
CXMatrix& operator = (const double &other) ;

CXMref operator ()(UINT x,UINT y);
CXMref operator ()(UINT x);


MATTYPE GetMatType()const;
bool isSquare () const { return (m_NumColumns == m_NumRowsH); }


private:
protected:
// internal variables
int m_NumColumns ; // number of columns in matrix
int m_NumRowsH ; // number of rows in matrix
double* m_pData ; // pointer to data, may be shared among objects
baseMatrix* m_pMat;
friend class CXMref;

};
其中的CXMref是为了给出矩阵元素的引用#include "XMatrix.h"
class CXMref
{
typedef double T;
public:
CXMref( CXMatrix& mm, size_t ii): m(mm), i(ii) {;}
CXMref( CXMref& mr): m(mr.m), i(mr.i) {;};
operator double() const{return m.m_pData[i]; }
double* operator& () const{return &m.m_pData[i]; }
double operator+ (double mux) const{return m.m_pData[i] + mux; }
double operator- (double mux) const{return m.m_pData[i] - mux; }
double operator* (double mux) const{return m.m_pData[i] * mux; }
double operator/ (double mux) const{return m.m_pData[i] / mux; }


double& operator = (const double& e) const{ if (m.shared()) m.clone(); return m.m_pData[i]= e; }

double& operator+= (double mux) const{if (m.shared()) m.clone();return m.m_pData[i] += mux; }
double& operator-= (double mux) const{if (m.shared()) m.clone();return m.m_pData[i] -= mux; }
double& operator*= (double mux) const{if (m.shared()) m.clone();return m.m_pData[i] *= mux; }
double& operator/= (double mux) const{if (m.shared()) m.clone();return m.m_pData[i] /= mux; }
ine ostream&operator<< (ostream& os){const double x = m.m_pData[i];os << x;return os;}
virtual ~CXMref();
private:
CXMref ();
CXMatrix& m;
size_t i;
};
能通过CXMref给出矩阵元素引用的方法有:
GetElement及()运算符
如:
Matrix X = CMO::zeros(1,7);
X (5)= 4;//X.GetElement(5);
首先是第一个问题:
在GetElement函数中,我需要构造一个CXMref 并返回它,但是我为什么需要强制转换一下呢?
CXMref CXMatrix::GetElement(int nPos) const
{

return CXMref ((CXMatrix&)*this,nPos);//为什么这里不能写成 return CXMref ((CXMatrix&)*this,nPos);
//如果按照后面的写法会得到这样的编译错误:error C2665: 'CXMref::CXMref' : none of the 3 overloads can convert parameter 1 from type 'const class CXMatrix'

}
这是第一个疑问。这个疑问虽然能够通过强制类型转换解决,但却使我比较迷惑。
第二个问题是,我在另外一个类CMO里面定义了一些静态的成员函数,对矩阵进行操作,包括了上面的CMO::zeros(1,7)(用来生成一个元素都是0的矩阵);
在这个类里面有这样一个函数:
void CMO::Display(const Matrix & mat)
{

for (int i = 0;i<mat.MatRowNo;i++)
{
for (int j = 0;j<mat.MatColNo;j++)
{
cout<<mat.GetElement(i,j)<<" ";//这里为什么不能写成:cout<<mat(i,j)<<" ";
//如果写成后面的,那么会得到这样的编译错误:error C2663: '()' : 2 overloads have no legal conversion for 'this' pointer
//其实GetElement和()运算符里面的代码是完全一样的,为什么后者就不能运行?

}
cout<<endl;
}
cout<<endl;
}
而如果把上面的函数定义成下面的形式它又是能够通过的:

void CMO::Display(Matrix & mat)
{

for (int i = 0;i<mat.MatRowNo;i++)
{
for (int j = 0;j<mat.MatColNo;j++)
{
cout<<mat(i,j)<<" ";
}
cout<<endl;
}
cout<<endl;
}
这种声明与前面的声明仅少了一个const,最后却有这样的差别,平时对C++的基础也看了不少,可是实在弄不清楚上面的两个问题究竟是怎么回事儿啊,请大虾们出手相助,谢谢!
注:所用编译器为VC6。






...全文
246 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
fietiger 2009-04-20
  • 打赏
  • 举报
回复
感谢各位的回复,尤其感谢beyond071与coverall多谢诸位
我现在的程序已经调好了,有感兴趣的我可以发给大家。我在自己的矩阵类的基础上做了一个非线性最小二乘拟合的程序,其编程精神完全取自Matlab,运算结果也基本一至。
fietiger@163.com
erwin1984 2009-04-20
  • 打赏
  • 举报
回复
把 const 修饰函数、修饰返回值、修饰对象或变量弄清楚了就好了。

void class1::func1() // 未修饰
{
}
void class1::func2() const //修饰函数
{
// 这里面使用到 class1 的成员的地方都会自动加上 const 约束,保证不修改其成员。
}
const int class1::func(){} //修饰返回值
const int &n = xxx; //修饰对象

其中 void class1::func2() const{...}, 说明该函数调用不会影响到 class1 的任何成员的修改, 所以无论 class1 obj1, const class obj1 都可以自由调用,
但是 如果是 const class1 obj1; 则不可以调用 class1::func1(); 因为 func1() 有可能修改 class1 的成员,所以违反了 const class1 obj1; 对 obj1 的约束。

beyond071 2009-04-20
  • 打赏
  • 举报
回复
一楼把问题解释清楚了,这里补充点解决办法。
问题一:主要是因为没有const型的拷贝构造函数,注意到拷贝构造过程中,目标源是不会被改动的,它们都应该是const!

CXMref( CXMatrix& mm, size_t ii): m(mm), i(ii) {;}
CXMref( CXMref& mr): m(mr.m), i(mr.i) {;};

应该改为:

CXMref( const CXMatrix& mm, size_t ii): m(mm), i(ii) {;}
CXMref( const CXMref& mr): m(mr.m), i(mr.i) {;};


问题二:Display函数中的const Matrix &mat在这个函数中是不能被修改的,而
CXMref operator ()(UINT x,UINT  y); 
并非是const型的函数,也就是说mat在这个过程有可能被修改(实现中并没有修改),但编译器是不会让这样有风险的程序通过的!
这有点类似vector的实现中,需要两个版本的operator[]一样。

T& operator[](size_type i){return data[i]} //索引并支持写入
const T& operator[](size_type i) const {return data[i]} //只支持索引

在楼主的程序中,目的如果是索引一个矩阵中(i,j)位置的元素,并返回一个值,那么这个函数就是const的,他不会改变CXMref中的成员。
声明如下即可解决问题:
CXMref operator ()(UINT x,UINT  y) const; 
wind_breez 2009-04-20
  • 打赏
  • 举报
回复
cout < <mat.GetElement(i,j) < <" ";//这里为什么不能写成:cout < <mat(i,j) < <" ";
mat是一个const对象,GetElement是一个const成员函数,operator ()不是。C++编译器设计,常对象只能调用常成员函数.
mengde007 2009-04-20
  • 打赏
  • 举报
回复
路过……
jn989 2009-04-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 coverallwangp 的回复:]
1.因为函数是const的,所以this指针式const的,而返回的是一个非const对象所以要强制转换
2.因为你传过来的是一个const的对象mat,getElement是个const函数所以可以调用。而mat(i,j)是用的操作符(),是个非const的,所以不能出错。
总结一下:const对象只能调用const的方法,非const的对象都可以调用。
[/Quote]
学习了……
  • 打赏
  • 举报
回复
return CXMref ((CXMatrix&)*this,nPos);//为什么这里不能写成 return CXMref ((CXMatrix&)*this,nPos);
//如果按照后面的写法会得到这样的编译错误:error C2665: 'CXMref::CXMref' : none of the 3 overloads can convert parameter 1 from type 'const class CXMatrix'

眼睛不好,没看出2者的不同

cout < <mat.GetElement(i,j) < <" ";//这里为什么不能写成:cout < <mat(i,j) < <" ";
//如果写成后面的,那么会得到这样的编译错误:error C2663: '()' : 2 overloads have no legal conversion for 'this' pointer
//其实GetElement和()运算符里面的代码是完全一样的,为什么后者就不能运行?

你重点把GetElement跟()贴出来看看,找的好累啊
jn989 2009-04-20
  • 打赏
  • 举报
回复
好长啊
简单看了下,感觉你这句“cout < <mat.GetElement(i,j) < <" ";//这里为什么不能写成:cout < <mat(i,j) < <" ";

可能因为Matrix类没有定义这种(x,y)运算符吧,()和(x,y)是不一样的
liubuweiright 2009-04-20
  • 打赏
  • 举报
回复
帮顶...
老邓 2009-04-20
  • 打赏
  • 举报
回复
CXMref CXMatrix::GetElement(int nPos) const
把const去掉试试
coverallwangp 2009-04-20
  • 打赏
  • 举报
回复
1.因为函数是const的,所以this指针式const的,而返回的是一个非const对象所以要强制转换
2.因为你传过来的是一个const的对象mat,getElement是个const函数所以可以调用。而mat(i,j)是用的操作符(),是个非const的,所以不能出错。
总结一下:const对象只能调用const的方法,非const的对象都可以调用。

64,681

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧