如何将Qt对象隐式转换为QString?

4

如何以标准 C++/Qt 的方式让下面所有被注释的代码都能正常运行?

class A {
public:
    A() { }
    virtual ~A() { }
    virtual QString toString() { return "A"; }
};

class B: A {
public:
    B() { }
    ~B() { }
    QString toString() { return "B"; }
};

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    A a_;
    B b_;

    // qDebug() << a_;  // I can make this work by overloading << yes?
    // qDebug() << b_;

    // QString x = a_;  // How do I make this work?
    // QString y = b_;

    QString s = a_.toString(); // What I'm doing at present
    qDebug() << b_.toString(); // What I'm doing at present

    return a.exec();
}

我有一些Qt类的实例,它们都是从同一个基类派生而来。我想以标准的方式将它们隐式地转换为字符串,以在Qt ui中显示:
我可以像上面那样使用自己的标准方法(如toString),显式地完成转换,但这不是隐式的。我更愿意遵循Qt或C++的约定,因为我相信有一种我不知道的约定。
这些字符串最终将显示在Q*View控件中,这意味着仅重载operator<<可能是不够的。

顺便说一下,定义一个空的公共构造函数和空的公共非虚析构函数是没有意义的。 - GManNickG
@GMan:谢谢,尽管上面的析构函数是public virtual - Peter McG
@Petermcg:一个需要明确定义(我确保我的列表已经承认了这一点),而另一个则不需要明确定义。 - GManNickG
1
@GMan:毫无疑问,两个析构函数都是公共虚函数,显式优于隐式。大多数Qt类在层次结构中都是这样声明的。 - Peter McG
@petermcg:当没有任何意义时,显式并不比隐式更好。当我看到一个声明的构造函数或析构函数时,我会认为它是有原因的,但你的三个或四个都没有原因,只会增加噪音(它们还具有微妙的影响,例如在技术上给你的类提供了一个非平凡的构造函数)。 - GManNickG
@GMan:这解释得更清楚了,谢谢... - Peter McG
1个回答

13

你只需要添加一个所谓的 转换函数

struct foo
{
    operator int() { return 5; }
};

foo f;
int i = f; // uses operator to convert to int

在你的情况下,只需将virtual QString toString()替换为virtual operator QString()


尽管如此,隐式类型转换通常是不被赞同的。不仅强制转换受到反对,而且现在你正在允许隐式地进行强制转换。 C++0x实际上允许我们在转换函数中添加explicit关键字以确保我们显式地强制转换,但我不知道哪些编译器支持这一特性。

我认为最好保留你已经拥有的代码,只需添加:

// I assume qDebug() is convertible to std::ostream
std::ostream& operator<<(std::ostream& stream, const A& val)
{
    stream << val.toString(); // would need to make function const, of course

    return stream;
}

同时保留其余明确的内容。


在C++0x中,explicit并不是新的特性,它已经存在于C++03中。因此,所有符合标准的编译器都应该支持它。 - hmuelner
2
@hmnuelner:关键字explicit,当然,但它在转换函数中的使用是全新的,这就是为什么我们不得不使用诸如安全布尔惯用法之类的东西。在C++03中,它唯一的用途是在构造函数中。 - GManNickG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接