代码中碰到一个奇怪的现象,在同样的函数中调用this指针,结果却有一个无法通过编译
1 // 读取连接信息 2 void ThirdWizardPage::ReadConnection() 3 { 4 QFile file("oracle.passwd"); 5 if(!file.open(QIODevice::ReadOnly)) 6 { 7 QMessageBox::information(this, tr("打开文件失败"), 8 tr("错误原因:%1").arg(file.errorString())); 9 return; 10 } 11 QDataStream in(&file); 12 Connection con; 13 int i = 0; 14 while(!in.atEnd()) 15 { 16 in >> con; 17 ui->comboBox->insertItem(i, con.strDatabase); 18 m_mapConnections.insert(i, con); 19 } 20 file.close(); 21 } 22 23 // 写入连接信息 24 void ThirdWizardPage::WriteConnection() const 25 { 26 QFile file("oracle.passwd"); 27 if(!file.open(QIODevice::WriteOnly)) 28 { 29 QMessageBox::information(const_cast<ThirdWizardPage*>(this),tr("打开文件失败"), 30 tr("失败原因:%1").arg(file.errorString())); 31 return; 32 } 33 QDataStream out(&file); 34 35 for(int i = 0;i < m_mapConnections.size();++i) 36 { 37 out << m_mapConnections[i]; 38 } 39 file.close(); 40 }
编译的错误提示是:
上面两个函数实现的功能是一个读取文件,一个写入文件,在两个函数中都使用到了QMessageBox::information函数,但是第二个函数中却必须将this指针强制转换成非const才能通过编译,仔细思考这个问题发现,是因为写入文件的函数定义为了常函数,即在函数体的大括号之前使用const修饰该函数。
以前学习C++primer的使用只知道定义为常函数是为了避免该函数修改类对象的成员变量。只是知道如果在常函数中修改了类的成员变量,那么编译时是通不过呢,至于为什么,怎么实现这样的控制的,却是不知道,只记住了怎么用。
下面说一下我自己的分析,众所周知,C++的所有成员函数都会有一个看不见的指针参数传入函数,该指针指向该对象(静态函数除外),那么可以推测,类的成员函数访问成员还是通过指针来访问的,即使有时候我们没有显示的使用this指针,系统也可能为我们默认填上,因为想要操作内存,归根结底还是要知道它存储在哪个位置,所以即便是那些没有指针的语言,我想,也是它的平台为它屏蔽了这些东西,而并不是这些东西不存在(这些东西是指指针)。
如此是否可以得出这样的结论:在常函数中,系统默认传入函数的this指针是const类型的。
那么,这样就可以解释的通了,如果在常函数中修改成员变量(即使不显示使用this指针,系统也会加上,因为要访问内存,必须使用指针),而现在的this指针又是const类型的,那么就会报错了,因此就可以实现限制在常函数中修改成员变量的功能了。
当然,以上全是凭借自己看到的现象以及对编程的一些悟性、理解做出的推测,不知道对不对。不过我的想法是,既然大师能想的出来,而大师也是人,只不过经验多些,所以自己如果思考的多了,也可能会成为大师的,嘿嘿,愿望。
最近开始看深入探索C++对象模型,就是讲C++的对象模型是如何实现的,希望在本书能将自己得出的这个结论验证一下。
C++中常函数内部的this指针也是const类型的