2012-01-18 27 views
19

Tengo una clase llamada Objeto que almacena algunos datos.¿Cómo devolver un objeto de clase por referencia en C++?

me gustaría devolverlo por referencia utilizando una función como esta:

Object& return_Object(); 

Entonces, en mi código, yo lo llamaría así:

Object myObject = return_Object(); 

He escrito un código como esto y compila. Sin embargo, cuando ejecuto el código, siempre obtengo una falla seg. ¿Cuál es la forma correcta de devolver un objeto de clase por referencia?

+1

no debería ser una referencia myObject? –

+0

Puede encontrar la respuesta aquí: http://stackoverflow.com/questions/3350385/how-to-return-an-object-in-c – MOHRE

+0

puede encontrar las formas aquí: http://stackoverflow.com/ preguntas/3350385/how-to-return-an-object-in-c – MOHRE

Respuesta

35

Probablemente esté devolviendo un objeto que está en la pila. Es decir, return_Object() probablemente se parece a esto:

Object& return_Object() 
{ 
    Object object_to_return; 
    // ... do stuff ... 

    return object_to_return; 
} 

Si esto es lo que estás haciendo, estás fuera de suerte - object_to_return ha ido fuera de alcance y ha destruido al final de return_Object, por lo que se refiere myObject a un objeto inexistente. Debe devolver por valor o devolver un Object declarado en un ámbito más amplio o new ed en el montón.

13

Solo puede devolver objetos no locales por referencia. El destructor puede haber invalidado algún puntero interno, o lo que sea.

No tenga miedo de devolver valores - it's fast!

18

Sólo puede utilizar

 Object& return_Object(); 

si el objeto devuelto tiene un alcance mayor que la función. Por ejemplo, puede usarlo si tiene una clase donde está encapsulado. Si crea un objeto en su función, use punteros. Si desea modificar un objeto existente, páselo como argumento.

class MyClass{ 
     private: 
     Object myObj; 

     public: 
     Object& return_Object() { 
      return myObj; 
     } 

     Object* return_created_Object() { 
      return new Object(); 
     } 

     bool modify_Object(Object& obj) { 
      // obj = myObj; return true; both possible 
      return obj.modifySomething() == true; 
     } 
    }; 
+0

Pero, ¿qué sucede si, en mi código de llamada, digo: 'MyClass mc; Objeto outsideObj = mc.return_Object; ' Si modifico las propiedades de' outsideObj' ¿eso realmente modifica el 'myObj' que está encapsulado dentro de' mc'? – livefree75

+0

Objeto outsideObj = mc.return_Object(); provocará una construcción de copia de la instancia 'outsideObj'. Ahora es una instancia separada, y si modificar uno afectaría al otro dependerá de cómo se haya implementado el constructor de copia. – UmNyobe

1

Bueno, tal vez no es una solución realmente hermosa en el código, pero es realmente hermosa en la interfaz de su función. Y también es muy eficiente. Es ideal si el segundo es más importante para usted (por ejemplo, está desarrollando una biblioteca).

El truco es el siguiente:

  1. Una línea A a = b.make(); se convierte internamente a un constructor de A, es decir, como si hubiera escrito A a(b.make());.
  2. Ahora b.make() debería dar como resultado una nueva clase, con una función de devolución de llamada.
  3. Todo este asunto puede manejarse bien solo por clases, sin plantilla.

Aquí está mi ejemplo mínimo. Verifique solo el main(), como puede ver, es simple. Los internos no son

Desde el punto de vista de la velocidad: el tamaño de una clase Factory::Mediator es de solo 2 punteros, que es más de 1, pero no más. Y este es el único objeto en todo lo que se transfiere por valor.

#include <stdio.h> 

class Factory { 
    public: 
    class Mediator; 

    class Result { 
     public: 
     Result() { 
      printf ("Factory::Result::Result()\n"); 
     }; 

     Result(Mediator fm) { 
      printf ("Factory::Result::Result(Mediator)\n"); 
      fm.call(this); 
     }; 
    }; 

    typedef void (*MakeMethod)(Factory* factory, Result* result); 

    class Mediator { 
     private: 
     Factory* factory; 
     MakeMethod makeMethod; 

     public: 
     Mediator(Factory* factory, MakeMethod makeMethod) { 
      printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n"); 
      this->factory = factory; 
      this->makeMethod = makeMethod; 
     }; 

     void call(Result* result) { 
      printf ("Factory::Mediator::call(Result*)\n"); 
      (*makeMethod)(factory, result); 
     }; 
    }; 
}; 

class A; 

class B : private Factory { 
    private: 
    int v; 

    public: 
    B(int v) { 
     printf ("B::B()\n"); 
     this->v = v; 
    }; 

    int getV() const { 
     printf ("B::getV()\n"); 
     return v; 
    }; 

    static void makeCb(Factory* f, Factory::Result* a); 

    Factory::Mediator make() { 
     printf ("Factory::Mediator B::make()\n"); 
     return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb); 
    }; 
}; 

class A : private Factory::Result { 
    friend class B; 

    private: 
    int v; 

    public: 
    A() { 
     printf ("A::A()\n"); 
     v = 0; 
    }; 

    A(Factory::Mediator fm) : Factory::Result(fm) { 
     printf ("A::A(Factory::Mediator)\n"); 
    }; 

    int getV() const { 
     printf ("A::getV()\n"); 
     return v; 
    }; 

    void setV(int v) { 
     printf ("A::setV(%i)\n", v); 
     this->v = v; 
    }; 
}; 

void B::makeCb(Factory* f, Factory::Result* r) { 
     printf ("B::makeCb(Factory*, Factory::Result*)\n"); 
     B* b = static_cast<B*>(f); 
     A* a = static_cast<A*>(r); 
     a->setV(b->getV()+1); 
    }; 

int main(int argc, char **argv) { 
    B b(42); 
    A a = b.make(); 
    printf ("a.v = %i\n", a.getV()); 
    return 0; 
} 
Cuestiones relacionadas