无法实现 operator==() 将自定义类对象与 QString 进行比较

Posted

技术标签:

【中文标题】无法实现 operator==() 将自定义类对象与 QString 进行比较【英文标题】:Cannot implement operator==() to compare a custom class object to a QString 【发布时间】:2016-02-07 05:21:26 【问题描述】:

我创建了以下类:

class videodup

public:
    videodup(QString vid = "", int m_a = 0, int m_b = 0);
    ~videodup() 
    QString video;
    bool operator==(const QString &str) const  return video == str; 
bool operator==(const videodup &dup) const return video == dup.video;
    QList<matchPair> matches;
;

videodup::videodup(QString vid = "", int m_a = 0, int m_b = 0)

    video = vid;
    matches.append(matchPair(m_a, m_b));

我认为它可以让我在QList::contains() 中使用QString,但它给了我一个错误:

/usr/local/Cellar/qt5/5.5.1_2/lib/QtCore.framework/Headers/qlist.h:981: error: invalid operands to binary expression ('videodup' and 'const videodup')
        if (i->t() == t)
            ~~~~~~ ^  ~
/Users/phire/Documents/workspace/VideoTwin/matchpair.h:30: candidate function not viable: no known conversion from 'const videodup' to 'QString &' for 1st argument
    bool operator==(QString &str)  return video == str; 
         ^

违规行是:

if (frame.videomatches.contains(vid))

这是解释上面一行的代码

struct frm

    QString file;
    int position;
    cv::Mat descriptors;
    QList<videodup> videomatches;
;
QList<frm> frames;

void MainWindow::findDupes(frm &frame)

    QString file = frame.file;
    UMat mat = frame.descriptors.getUMat(cv::ACCESS_RW);
    UMat indices;
    UMat dists;
    if (!mat.isContinuous() || mat.empty())
        return;
    QTime timestamp(0,0,0,0);
    timestamp = timestamp.addMSecs(frame.position);
    try
    
        mat = mat.reshape(1,1);
        index.knnSearch(mat,indices,dists,5);
    
    catch (Exception e)
    
        qWarning() << "index search failure" << e.err.c_str() << e.msg.c_str();
    
    catch (exception& e)
    
        qWarning() << "index search failure" << e.what();
    
//    qDebug() <<  "indices cols" << indices.cols << "dists cols" << dists.cols;
    db.transaction();
    QSqlQuery matches(db);
    QStringList tempmatches;
    Mat indicesMat = indices.getMat(cv::ACCESS_READ);
    Mat distsMat = dists.getMat(cv::ACCESS_READ);

    for (int i = 0; i < indicesMat.cols; i++)
    
        if (indicesMat.at<int>(0,i) == -1 || distsMat.at<int>(0,i) > 12800)
            continue;
        try
        
            QTime matchtime(0,0,0,0);
            int matchms = frames.at( indicesMat.at<int>(0,i)).position;
            QString vid = frames.at( indicesMat.at<int>(0,i)).file;
            matchtime = matchtime.addMSecs(matchms);
            int temp = distsMat.at<int>(0,i);
            tempmatches.append(QString::number( indicesMat.at<int>(0,i)));
            if (frame.videomatches.contains(vid))
            
                matchPair pair(frame.position, indicesMat.at<int>(0,i));
                frame.videomatches[ frame.videomatches.indexOf(vid) ].matches.append(pair);
            
            else
            
                frame.videomatches.append(videodup(vid,frame.position, indicesMat.at<int>(0,i)));
            
//            qDebug() << frame.file << "frame"<<  timestamp.toString("hh:mm:ss") << "match at"<< vid << matchtime.toString("hh:mm:ss") << "distance" << temp;
        
        catch (Exception e)
        
            qWarning() << "failure in indices" << e.err.c_str() << e.msg.c_str() << e.func.c_str();
        
        catch (exception &e)
        
            qWarning() << "failure in indices" << e.what();
        
    
    QString temp(tempmatches.join(","));
    matches.prepare("UPDATE frames SET matches = :matches WHERE file = :file AND position = :position");
    matches.bindValue(":matches",temp);
    matches.bindValue(":file",frame.file);
    matches.bindValue(":position",frame.position);
    if (!matches.exec())
        qWarning() << "couldn't add matches to frame in database";
    db.commit();

如何使我的自定义类与QString 相媲美?

【问题讨论】:

Neal 是同一个代码,还是从那以后发生了变化?不幸的是,您删除了粘贴,我再次忘记了(首先并不清楚)frameframe.videomatchesvid 是什么。这很重要。 试图只粘贴相关位 pastebin.com/8WP8jT5P 好的,我看到了你的问题,正在考虑如何规避它。使用 STL 很容易实现,使用 Qt 我需要考虑一下。 好吧,伙计们添加了额外的 operator==() 定义做到了,那么谁先说的呢? 老实说,我认为是迈克尔,我在破译运算符的确切顺序时迷路了。 【参考方案1】:

错误消息抱怨试图比较“videodup”和“const videodup”。

您只需要定义一个bool operator==(const videodup &amp;) const 函数。

错误中提到了QString,因为这是videodup::operator==() 接受的唯一类型,因此编译器尝试转换为QString,但发现它不能。

【讨论】:

迈克尔,不知怎么的,我反其道而行之。 bool QList::contains(const T &amp; value) const; 表示 QList 只会接受 videodup 并试图将 QString 转换为它。我错了吗? 另外,如果您看我上面的通话分析,如果我没看错的话,我将不胜感激。 我只是按照错误消息所说的去做。第一个说qlist.h:981 正在尝试比较videodupconst videodup 对象。第二个说matchpair.h:30 正在尝试将const videodup 对象转换为QString&amp;,因此它可以调用bool operator==(QString &amp;str),但它无法执行转换。 第二个陈述如何与operator== 想要Tvideodup)这一事实相吻合?为什么它试图反过来转换?问题是(我理解您的思路!)通过查看代码,那里没有const videodup,可能只有videodupQString 创建。 错误消息表明QList 包含videodup 的对象,而不是QString 对象。 Qlist 代码试图比较几个 videodup 对象但不能直接这样做,因为没有直接处理它们的operator==()。编译器确实看到了采用QStringoperator==(),因此尝试转换但不能。我认为如果 OP 从“违规行”中显示 frameframe.videomatchesvid 的声明,这一切可能会更清楚。【参考方案2】:

好的,这就是我认为的事情。首先,也是最重要的,

bool QList::contains(const T & value) const;

此函数需要 (a) T 类型的对象(它存储的类型)或 (b) R 类型的对象,该对象可以通过某种方式转换为 T。具体如何?通过转换运算符 R::T() 或 c'tor 或 R 采用 T: R:R(T&amp;)。看,你正好有后者可用。 videodup::videodup(QString&amp;, int=default, int=default).

这是真正的问题:

一旦编译器通过上述构造函数将QString成功转换为videodup,它就想按照QList::contains(const T&amp;)函数的要求调用videodup::operator==(const videodup&amp;),但找不到。因此,正如 Michael 所说,您需要取消注释并实现 videodup::operator==(const videodup&amp;)

编辑:

我也认为为了避免这种隐式转换,我们可以使用 STL std::find&lt;Iterator, T&gt; 函数,并利用 videodup::operator==(const QString&amp;)。为此,只需替换

if (frame.videomatches.contains(vid)) 

const auto &matches = frame.videomatches;
if (std::find(matches.cbegin(), matches.cend(), vid) != matches.cend()) 

我很确定这会直接使用现有的运算符,避免不必要的转换。

【讨论】:

以上是关于无法实现 operator==() 将自定义类对象与 QString 进行比较的主要内容,如果未能解决你的问题,请参考以下文章

无法将自定义 IBDesignable 类链接到情节提要上的 UIButton

为啥委托方法需要将自定义类托管对象上下文的内容保存在委托类托管对象上下文中?

无法将自定义对象从 API 保存到核心数据

无法将自定义数据类型转换为字符串?

如何使用 toDF() 将自定义 Java 类对象的 RDD 转换为 DataFrame?

如何将自定义类分配给 TableViewController