Question

Im calling a method foo by const ref:

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

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

This piece of code does not only compile, it creates a new instance of Entity with its default values in the scope of foo. I'd expect that this does not compile or at least crashes.

If I call foo correctly (foo(*e)), everything works as suspected and I see the right values of Entity within foo.

Im using mingw supplied with Qt 4.7.

Here's the interface of 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;
};
Was it helpful?

Solution

[Edited] You have an implicit converting constructor (that also happens to be a default constructor) from Entity* (via parent QObject*) to Entity and it's being used to create a temporary instance to pass in.

For this reason I always suggest by default making all single-parameter callable constructors (for example where all but one parameter is defaulted) explicit and avoiding implicit conversion operators except when they exactly perform the conversion semantics that would be expected in all circumstances. In other cases make the conversions available through explicit methods.

There are occasionally cases where implicit conversions are useful, and each one should be evaluated on a case-by-case basis.

OTHER TIPS

Actually:

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

You are creating a new temporary entity from a pointer to an Entity (which is also a pointer to a QObject).

It compiles because it's valid.

As Mark pointed out, the implicit conversion from Entity* to Entity is done through the constructor which takes an argument of type "pointer to QObject". To test this out, change the inheritance to private, you should get a compilation error.

To avoid such mistakes in the future, declare conversion constructors as explicit.

Your Entity constructor takes a QObject* argument and is not marked as explicit. That means that an Entity may be constructed implicitly from an Entity*, which is pretty bad news.

Further, because the function takes a ref-to-const, this implicitly-constructed temporary can be bound to that function argument.

Mark the constructor explicit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top