5

我对此有点困惑。假设我有一个助手类Data

class Data
{
public:
    Data(const QVariant &value) : m_Variant(value) { }
    operator QString() const { return m_Variant.toString(); }

private:
    QVariant m_Variant;
};

然后当我这样做时:

Data d("text");
QString str = d; //str becomes "text"

它有效,但当我继续这样做时:

Data d2("text2");
str = d2; //does not compile

它没有抱怨:

ambiguous overload for 'operator=' (operand types are 'QString' and 'Data')
candidates are:
...
QString &operator=(const QString &);
QString &operator=(QString &&);
QString &operator=(const char*); <near match>
    no known conversion from Data to const char*
QString &operator=(char);

但即使提供

operator const char*() const;

没有帮助。关于转换的消息消失了,错误保持不变。除了添加之外有没有办法解决这个问题

QString &operator=(const Data &data);

QString或显式调用

str = QString(d2);

?

我很困惑,因为编译器清楚地正确推断出左操作数是 aQString并且它显然试图将转换从sData之一调用,但即使定义了这样的转换它仍然不起作用。QStringoperator=

编辑: 问题似乎来自不同operator T()成员的多个定义。在这种情况下operator int()

4

1 回答 1

6

我无法使用 Qt 库访问在线编译器,但这是我从 and 的公共文档中拼凑的QString内容QVariant

#include <iostream>

struct QString 
{
    QString() = default;
    QString(QString const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    QString &operator=(const QString &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return *this; }

    QString(char const*)  { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    QString &operator=(const char*) { std::cout << __PRETTY_FUNCTION__ << '\n'; return *this; }

    QString(char)  { std::cout << __PRETTY_FUNCTION__ << '\n'; }    
    QString &operator=(char) { std::cout << __PRETTY_FUNCTION__ << '\n'; return *this; }    
};

struct QVariant
{
    QVariant(QString const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    QVariant(char const*)  { std::cout << __PRETTY_FUNCTION__ << '\n'; }
};

struct Data
{
    Data(QVariant const&) { std::cout << __PRETTY_FUNCTION__ << '\n'; }
    operator QString() const  { std::cout << __PRETTY_FUNCTION__ << '\n'; return QString(); }
    operator int() const { std::cout << __PRETTY_FUNCTION__ << '\n'; return QString(); }
};

int main()
{
    Data d("text");
    QString str = d;

    Data d2("text2");
    str = d2;
}

现场示例

和的直接初始化,通过构造函数进行转换d("text")d2("text2")char const* -> QVariant

QVariant::QVariant(const char*)
Data::Data(const QVariant&)

复制初始化 QString str = d省略了对由生成QString的临时QString对象的复制构造函数的调用

Data::operator QString() const

现在是错误:尝试将各种赋值运算符重载与您的参数相匹配的赋值。一旦有多个转换运算符(to和 to eg),您将获得重载决议歧义,因为既有常规赋值又有(可以取)。str = d2QString::operator=DataDataQStringintQStringoperator=(QString)operator=(char)int

TL;DR只有一条施工路线:char const* -> QVariant -> Data. 但是有两条路线Data -> QStringData -> int -> char这导致赋值运算符的有效参数。

修复:explicit在您自己的代码中使用转换运算符(或删除其中一个或多个)。

于 2015-09-18T13:35:19.677 回答