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

时间:2016-02-07 05:21:26

标签: c++ qt operator-overloading qt5.5

我创建了以下类:

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));
}

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

/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相媲美?

2 个答案:

答案 0 :(得分:1)

好的,这就是我认为这里的锣。首先,最重要的是,

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

此函数需要(a)类型为T的对象(它存储的类型)或(b)类型R的对象,可以某种方式转换为T。究竟怎么样?通过转化运算符R::T()或带有RT的c'tor或R:R(T&)。看,你有完全可用的后者。 videodup::videodup(QString&, int=default, int=default)

这就是实际问题:

一旦编译器通过上述构造函数成功将QString转换为videodup,它就会根据videodup::operator==(const videodup&)函数的要求调用QList::contains(const T&),并且可以找不到一个。因此,您需要取消注释并实现videodup::operator==(const videodup&),就像Michael所说的那样。

编辑:

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

if (frame.videomatches.contains(vid)) {

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

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

答案 1 :(得分:1)

错误消息是抱怨尝试比较'videodup'和'const videodup'。

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

错误中提到了

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