C++: Ссылки как аргументы конструктора, помощь

У меня есть базовый класс (Base) чей конструктор принимает ссылку в качестве аргумента. В моем производном классе это конструктор, я вызываю конструктор суперкласса и, конечно, мне нужно передать ссылку в качестве аргумента. Но я должен получить этот аргумент из метода, тип возвращаемого значения по значению...

Я приведу короткий пример:

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.
    }
};

Как я могу решить эту проблему?

4 ответа

Решение

Измените Базовый класс на:class Base { public: Base(const MyType &obj) { /* do something with the obj */} };

Обновление: если вы хотите изменить объект, у вас явно не может быть const ссылка. В этом случае вы можете:

1) Передайте параметр по значению. Это будет иметь дополнительные издержки для копии, но избегайте необходимости явно освобождать ее позже.

2) Изменить MyOtherType::getMyTypeObj() в

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

}

В этом случае не забудьте удалить объект после того, как с ним покончено.

Шутки в сторону? На ваш вопрос есть ответ. Измените либо тип параметра на конструктор Base, либо тип возвращаемого значения getMyTypeObj(), чтобы типы были совместимы.

Мне кажется, что есть два способа решить это.

  1. Измените конструктор Base, чтобы он принимал объект MyType по значению, а не по ссылке. Это скопирует временный объект и решит проблемы области видимости.

  2. Кроме того, вы можете сделать копию объекта MyType в Derived и передать ссылку на него.

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

Вариант 1 проще, и я бы в целом порекомендовал его.
Вариант 2 на случай, если какое-то другое ограничение не позволит вам изменить конструктор Base,

Проблема вызвана тем, что GetMyTypeObj() возвращает копию 'obj', которая основана на стеке, поэтому компилятор создает временную переменную внутри вашего конструктора, область действия которой - это просто вызов конструкции Base().

Другие вопросы по тегам