2012-01-18 18 views
19

Mam klasy o nazwie Object, która przechowuje niektóre dane.Jak zwrócić obiekt klasy przez odniesienie w C++?

Chciałbym zwrócić go poprzez odniesienie przy użyciu funkcji takich jak to:

Object& return_Object(); 

Następnie w moim kodu, nazwałbym to tak:

Object myObject = return_Object(); 

Pisałem kod jak to i to kompiluje. Jednak po uruchomieniu kodu konsekwentnie otrzymuję błąd seg. Jaki jest właściwy sposób zwracania obiektu klasy przez odniesienie?

+1

Czy myObject nie powinien być poleceniem? –

+0

Możesz znaleźć odpowiedź tutaj: http://stackoverflow.com/questions/3350385/how-to-return-an-object-in-c – MOHRE

+0

możesz znaleźć tutaj: http://stackoverflow.com/ pytania/3350385/how-to-return-an-object-in-c – MOHRE

Odpowiedz

35

Prawdopodobnie zwrócisz obiekt znajdujący się na stosie. Oznacza to, że prawdopodobnie return_Object() wygląda następująco:

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

    return object_to_return; 
} 

Jeśli to, co robisz, masz pecha - object_to_return upadł poza zakres i zostały zniszczone pod koniec return_Object, więc myObject odnosi do nieistniejącego obiektu. Musisz albo zwrócić wartość, albo zwrócić Object zadeklarowaną w szerszym zakresie lub new ed na stercie.

13

Można zwracać obiekty inne niż lokalne przez odwołanie. Destruktor mógł unieważnić jakiś wewnętrzny wskaźnik lub cokolwiek innego.

Nie bój się zwracać wartości - it's fast!

18

można używać tylko

 Object& return_Object(); 

jeżeli obiekt zwrócony ma większy zakres niż funkcji. Na przykład możesz go użyć, jeśli masz klasę, w której jest enkapsulowany. Jeśli utworzysz obiekt w swojej funkcji, użyj wskaźników. Jeśli chcesz zmodyfikować istniejący obiekt, przekaż go jako argument.

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

Ale co się stanie, jeśli w moim kodzie wywoławczym mówię: 'MyClass mc; Object outsideObj = mc.return_Object; ' Jeśli następnie zmienię właściwości' outsideObj', to faktycznie modyfikuje on 'myObj', który jest zamknięty wewnątrz' mc'? – livefree75

+0

Obiekt outsideObj = mc.return_Object(); sprowokuje kopię konstrukcji instancji 'outsideObj'. Jest teraz oddzielną instancją i to, czy modyfikacja wpłynie na drugą, zależy od tego, w jaki sposób został zaimplementowany konstruktor kopii. – UmNyobe

1

Cóż, może nie jest to naprawdę piękne rozwiązanie w kodzie, ale jest naprawdę piękne w interfejsie funkcji. Jest również bardzo wydajny. Idealnie jest, gdy drugi jest dla ciebie ważniejszy (na przykład tworzymy bibliotekę).

Sztuką jest taka:

  1. Linia A a = b.make(); jest wewnętrznie przekształca się w konstruktora A, czyli jak gdyby napisane A a(b.make());.
  2. Teraz b.make() powinien spowodować nową klasę, z funkcją zwrotną.
  3. Cała ta może być dobrze obsługiwana tylko przez klasy, bez żadnego szablonu.

Oto mój minimalny przykład. Sprawdź tylko main(), jak widać, jest to proste. Wewnętrzne nie są.

Z punktu widzenia prędkości: rozmiar klasy Factory::Mediator to tylko 2 wskaźniki, czyli więcej niż 1, ale nie więcej. I jest to jedyny przedmiot w całej rzeczy, który jest przekazywany przez wartość.

#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; 
} 
Powiązane problemy