8

foo我通过以下方式调用方法const ref

// method, which is being called
void foo(const Entity & ent);

// call
Entity* e = new Entity;
foo(e);    // wrong: missing * but compiles

这段代码不仅编译,它创建一个新实例,Entity其默认值在foo. 我希望这不会编译或至少崩溃。

如果我foo正确调用 ( foo(*e)),一切都会正常工作,并且我会看到Entitywithin的正确值foo

我使用 Qt 4.7 提供的 mingw。

这是 的界面Entity

class Entity : public QObject
{
    Q_OBJECT

public:
    Entity (QObject* parent = NULL);

    long getId() const { return this->id; }
    void setId(const long id) { this->id = id; }

    QString getName() const { return this->name; }
    void setName(const QString & name) {this->name = name; }

private:
    QString name;
    long id;
};
4

3 回答 3

15

[已编辑]您有一个从(通过 parent )到的隐式转换构造函数(恰好是默认构造函数),它被用来创建一个临时实例以传入。Entity*QObject*Entity

出于这个原因,我总是建议默认使所有单参数可调用构造函数(例如,除了一个参数之外的所有参数都是默认的)显式并避免隐式转换运算符,除非它们完全执行在所有情况下都预期的转换语义。在其他情况下,通过显式方法使转换可用。

在某些情况下,隐式转换很有用,应根据具体情况对每种情况进行评估。

于 2011-09-20T13:12:49.133 回答
2

实际上:

Entity* e = new Entity;
foo(e); //will call: 
-> foo ( Entity(e) ) ; //will call:
-> foo ( Entity((QObject*) e );

您正在从指向实体的指针(也是指向 QObject 的指针)创建一个新的临时实体。

它编译是因为它是有效的。

正如 Mark 所指出的,从 Entity* 到 Entity 的隐式转换是通过构造函数完成的,该构造函数采用“指向 QObject 的指针”类型的参数。要对此进行测试,请将继承更改为私有,您应该会收到编译错误。

为避免将来出现此类错误,请将转换构造函数声明为explicit.

于 2011-09-20T13:23:27.370 回答
1

您的Entity构造函数接受一个QObject*参数并且未标记为explicit. 这意味着 aEntity可以从 a隐式Entity*构造,这是一个非常坏的消息。

此外,由于该函数采用 ref-to- const,因此这个隐式构造的临时变量可以绑定到该函数参数。

标记构造函数explicit

于 2011-09-20T13:24:27.963 回答