C++报错const Dataset作为this参数丢弃限定符如何解决?
问题解决方法
错误原因
编译错误的核心原因是:const修饰的Dataset对象只能调用const成员函数,但你当前的Dataset类和内部嵌套的Row类都只提供了非const版本的operator[],调用B[k][j]时,const对象B调用非const的operator[]会丢弃const限定符,不符合C++语法规则。
修复步骤
你需要补充两个const版本的operator[]实现,同时优化相关接口的const兼容性:
- 给内部
Row类新增const版本的下标运算符,用于只读访问行内元素 - 给外层
Dataset类新增const版本的下标运算符,用于只读访问数据集的行 - 同步修改拷贝构造函数的入参为const引用,保证const对象可以正常拷贝
- 可选优化赋值运算符逻辑,增加尺寸不匹配时的内存重分配,避免越界访问
修改后完整代码(关键改动已标注)
#include <iostream> using namespace std; typedef unsigned int uInt32; template <class StorageType> class Dataset { private: class Row { private: uInt32 NCol; StorageType *Data; public: Row(){ Data = NULL; } void SetCol(uInt32 Col){ if((Data = new StorageType[Col]) == NULL) { cout << "Dataset::memory exhausted ... exiting" << endl; exit(1); } NCol = Col; } ~Row(){ if(Data != NULL) { delete []Data; } } // 原有非const版本,用于修改元素 StorageType &operator[](uInt32 Col){ return Data[Col]; } // 新增const版本,用于只读访问const Row的元素 const StorageType &operator[](uInt32 Col) const { return Data[Col]; } }; Row *Array; uInt32 NRow; uInt32 NCol; public: Dataset(uInt32 Row, uInt32 Col) { if((Array = new Row[Row]) == NULL){ cerr << "Dataset::memory exhausted ... exiting" << endl; exit(1); } register uInt32 i; for(i = 0;i < Row;i++) { Array[i].SetCol(Col); } NRow = Row; NCol = Col; } // 拷贝构造函数入参改为const引用,兼容const对象拷贝 Dataset(const Dataset<StorageType> &B) { NRow = B.GetNoOfRows(); NCol = B.GetNoOfCols(); if((Array = new Row[NRow]) == NULL){ cerr << "Dataset::memory exhausted ... exiting" << endl; exit(1); } register uInt32 i,j; for(i = 0;i < NRow;i++) { Array[i].SetCol(NCol); for(j = 0;j < NCol;j++) { Array[i][j] = B[i][j]; } } } virtual ~Dataset() { delete[] Array; } // 原有非const版本,用于修改行元素 Row &operator[](uInt32 Row){ return Array[Row]; } // 新增const版本,用于只读访问const Dataset的行 const Row &operator[](uInt32 Row) const { return Array[Row]; } uInt32 GetNoOfRows() const { return NRow; } uInt32 GetNoOfCols() const { return NCol; } Dataset<StorageType> operator*(Dataset<StorageType> const &B) { Dataset<StorageType> Temp(NRow,B.GetNoOfCols()); if(NCol == B.GetNoOfRows()) { uInt32 Row = B.GetNoOfRows(); uInt32 Col = B.GetNoOfCols(); register uInt32 i, j, k; register StorageType Product; for(i = 0;i < NRow;i++) { for(j = 0;j < Col;j++) { Product = 0; for(k = 0;k < Row;k++) { Product += Array[i][k]*B[k][j]; // 此处错误已修复 } Temp[i][j] = Product; } } } else { cerr << "Dataset::matrices aren't compatible for multiplication" << endl; } return (Temp); } // 赋值运算符优化:增加尺寸不匹配时的内存重分配逻辑,避免越界访问 void operator=(Dataset<StorageType> const &B) { // 如果当前尺寸和待赋值对象尺寸不一致,先释放原有内存重新分配 if(NRow != B.GetNoOfRows() || NCol != B.GetNoOfCols()){ delete[] Array; NRow = B.GetNoOfRows(); NCol = B.GetNoOfCols(); Array = new Row[NRow]; for(uInt32 i=0;i<NRow;i++){ Array[i].SetCol(NCol); } } register uInt32 i, j; uInt32 Row = B.GetNoOfRows(); uInt32 Col = B.GetNoOfCols(); for(i = 0;i < Row;i++) { for(j = 0;j < Col;j++) { Array[i][j] = B[i][j]; // 此处错误已修复 } } } };
功能验证用例
int main(){ Dataset<double> a(2,3); Dataset<double> b(3,2); // 初始化a和b的元素 for(int i=0;i<2;i++){ for(int j=0;j<3;j++){ a[i][j] = i*3 + j + 1; } } for(int i=0;i<3;i++){ for(int j=0;j<2;j++){ b[i][j] = i*2 + j + 1; } } // 测试const参数的乘法 Dataset<double> c = a * b; // 输出结果 for(int i=0;i<c.GetNoOfRows();i++){ for(int j=0;j<c.GetNoOfCols();j++){ cout << c[i][j] << " "; } cout << endl; } return 0; }
内容的提问来源于stack exchange,提问作者Nostalgic
相关产品推荐
相关产品推荐

