views:

96

answers:

4

Hi,

I have a base class(Base) whose constructor takes a reference as argument. In my derived class its constructor, I call the superclass-constructor and of course I need to pass a reference as argument. But I have to obtain that argument from a method of which the return type is by value...

I will give a short example:

class Base
{
public:
    Base(MyType &obj) { /* do something with the obj */}
};

class Derived : public Base
{
public:
    Derived(MyOtherType *otherType) :
         Base(otherType->getMyTypeObj()) // <--- Here is the error because (see *)
    {
         // * 
         // getMyTypeObj() returns a value and
         // the Base constructor wants a reference...
    }
};

class MyOtherType
{
public:
    MyType getMyTypeObj()
    {
         MyType obj;
         obj.setData( /* blah, blah, blah... Some data */);
         return obj; // Return by value to avoid the returned reference goes out of scope.
    }
};

How can I solve this problem?

A: 

The problem is caused by the GetMyTypeObj() returning a copy of 'obj', which is stack-based, so the compiler makes a temporary variable inside your constructor, the scope of which is just that Base() construction call.

JBRWilkinson
+3  A: 

Change the Base class to: class Base { public: Base(const MyType &obj) { /* do something with the obj */} };

Update: If you want to modify obj you cannot obviously have a const reference. In that case you can either:

1)Pass the parameter by value. That will have the overhead for the copy but avoid having to free it explicitly later.

2) Change MyOtherType::getMyTypeObj() to

MyType& MyOtherType::getMyTypeObj()
{
    MyType* obj = new MyType();
    obj->setData( /* blah, blah, blah... Some data */);
    return *obj;

}

In this case, remember to delete the object after you are done with it.

Rajorshi
This would work unless `/* do something with the obj */` meant he wants to modify obj.
5ound
of course, this is where overloading comes in handy :)
Cogwheel - Matthew Orlando
Of course. But then, if he wants to modify the object, he is probably better off making his own copy. Updated my answer. Thanks
Rajorshi
+1  A: 

Seriously? Your question has the answer in it. Change either the type of the parameter to the Base constructor, or the type of the return value of getMyTypeObj() so that the types are compatible.

John
+1: it seems like it's all your code, so why workaround an issue you can fix?
rubenvb
A: 

It seems to me that there are two ways to solve this.

  1. Change the Base constructor to accept a MyType object by value instead of by reference. This will copy the temporary object and solve scope problems.

  2. Alternatively, you can make a copy of the MyType object in Derived and pass a reference to that.

class Derived : public Base
{
public:
    Derived(MyOtherType *otherType) :
        Base(m_myType) ,
        m_myType(otherType->getMyTypeObj())
    {
        // ...
    }
private:
    MyType m_myType;
};

Option 1 is simpler and I would generally recommend it.
Option 2 is just in case some other constraint prevents you changing the Base constructor,

Michael J