【问题标题】:C++ Error - passing 'const Dataset<double>' as 'this' argument discards qualifiers[-fpermissive]C++ 错误 - 将 'const Dataset<double>' 作为 'this' 参数传递会丢弃限定符 [-fpermissive]
【发布时间】:2021-08-22 15:55:00
【问题描述】:

我有一个如下所示的类数据集

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;
                }
            }
            StorageType &operator[](uInt32 Col){
                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;
    }

    Dataset(Dataset<StorageType> &B)
    {
        NRow = B.GetNoOfRows();
        NCol = B.GetNoOfCols();

        if((Array = new Row[NRow]) == NULL){
            cerr << "Martix::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;
    }

    Row &operator[](uInt32 Row){
        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];  **-->  error here**
                    }
                    
                    Temp[i][j] = Product;
                }
            }
        }
        else
        {
            cerr << "Dataset::matrices aren't compatible for multiplication" << endl;
        }
        return (Temp);
    }

    void operator=(Dataset<StorageType> const &B)
    {
        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]; **-->  error here**
            }
        }
    }
};

我收到以下错误

将 'const Dataset' 作为 'this' 参数传递会丢弃 限定符[-fpermissive]

在标记的地方 --> 这里有错误。 . 我需要使用 operator* 将调用者类中的两个数据集相乘,并且必须使用 const 参数。我该如何解决?一些代码示例会有所帮助。

【问题讨论】:

  • B参数是const,但是operator[]对非const对象进行操作。您需要第二个版本的 operator[] 返回一个 const ref,并声明一个 const 成员函数。
  • @Peter - Reinstate Monica 我需要从另一个地方调用重载的运算符,如果我从 B 参数中删除 const 我会得到另一个错误--> cannot bind non-const lvalue reference of type Dataset&lt;double&gt;&amp; to an rvalue of type DataSet&lt;double&gt;
  • 首先,如果您提取 minimal reproducible example 会有所帮助,其中包括剥离所有模板内容并使用 C++ 类型,而不是 uInt32 类型定义。无论如何,请在此处搜索“基本 C++ 资源”。原因是,您的代码中有很多不良习惯可能来自不良的学习资源。例如,如果任何教程教你检查 newNULL 的返回值,那么该教程完全过时或不好。
  • @UlrichEckhardt 在通过一些简单的编辑使代码编译后(更改类型 Row 的名称以避免名称冲突,包括标题),它编译得很好。这是为什么?为什么我可以在 const B 上调用非常量运算符 []? (gcc 10.2, VC.) ...godbolt.org/z/56necn4rd

标签: c++


【解决方案1】:

您提供的代码产生了更多错误,因此它不可能只产生您显示的错误。

在修复了相当琐碎的问题后,代码编译得很好(直到最近的编译器开始抱怨我最后一次使用的禁止寄存器存储类是在 1988 年左右),请参阅https://godbolt.org/z/56necn4rd

清理您的代码并显示仍然存在的错误(如果有)。

我注意到该错误似乎与您的类 Dataset 是一个模板这一事实有关。同一类的非模板版本(我只是将 StorageType 替换为 int)会导致预期的错误(从 const 对象调用非常量成员函数)。

原因似乎是该错误仅在模板代码实际实例化时发生,也就是说,如果某些代码直接或间接地调用违反 const 的函数。这是一个示例(live 在 Godbolt)。

从技术上讲,f() 的定义违反了 const,因为主体从非 const 对象调用 g()。 (禁止这样做的原因是因为g() 可能会更改 const f() 承诺不做的对象。)但是模板是特殊的——例如,SFINAE 模式使得拥有通常会创建的代码成为可能在为给定模板参数创建模板中的潜在重载列表时出现编译器错误;这些重载只是在实例化时被丢弃类似的东西可能在这里起作用;只是 没有 的重载是可行的,但这只是在实例化时检测到(并且相关)。

#include <iostream>
using namespace std;

template<class T> struct TC
{
    void g() {}
    // We can violate constness in member functions in templates
    // as long as nobody calls them: 
    void f(const TC<T> &crtc) const { crtc.g(); } 
};

int main()
{
    TC<int> tc;
    const TC<int> &crtc = tc;
    // crtc.f(crtc); // <-- comment this in to get the error.
}

【讨论】:

    猜你喜欢
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多