我通过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)
),一切都会被怀疑,我会在Entity
内看到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;
};
答案 0 :(得分:15)
[已编辑]您有Entity*
(通过父QObject*
}到Entity
的隐式转换构造函数(也恰好是默认构造函数)它被用来创建一个临时实例来传入。
出于这个原因,我总是建议默认情况下使所有单参数可调用构造函数(例如,除了一个参数之外的所有参数都是默认的)显式并避免隐式转换运算符,除非它们完全执行转换语义在所有情况下都可以预期。在其他情况下,通过显式方法使转换可用。
有时隐式转换很有用,每个转换应根据具体情况进行评估。
答案 1 :(得分:2)
实际上:
Entity* e = new Entity;
foo(e); //will call:
-> foo ( Entity(e) ) ; //will call:
-> foo ( Entity((QObject*) e );
您正在从指向实体的指针(也是指向QObject的指针)创建新的临时实体。
它编译因为它有效。
正如Mark所指出的,从Entity *到Entity的隐式转换是通过构造函数完成的,该构造函数接受类型为“指向QObject的指针”的参数。要对此进行测试,将继承更改为private,您应该收到编译错误。
为避免将来出现此类错误,请将转化构造函数声明为explicit
。
答案 2 :(得分:1)
您的Entity
构造函数采用QObject*
参数,未标记为explicit
。这意味着Entity
可以从Entity*
隐式 构建,这是个坏消息。
此外,因为函数采用ref-to - const
,所以这个隐式构造的临时可以绑定到该函数参数。
标记构造函数explicit
。