Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

zwracanie wskaźnika *this przez referencję i wartość.

Ostatnio zmodyfikowano 2016-09-20 10:51
Autor Wiadomość
pozdro600
Temat założony przez niniejszego użytkownika
zwracanie wskaźnika *this przez referencję i wartość.
» 2016-09-19 21:29:18
Mam kod:
C/C++
#include <iostream>
using namespace std;

class Calc
{
private:
    int m_value;
   
public:
    Calc() { m_value = 0; }
   
    Calc add( int value ) { m_value += value; return * this; }
    Calc sub( int value ) { m_value -= value; return * this; }
   
    int getValue() { return m_value; }
};


int main()
{
    Calc calc;
    calc.add( 5 ).sub( 1 );
   
    std::cout << calc.getValue() << '\n';
    return 0;
}
Skoro wskaźnik this wskazuje na obiekt, na którym właśnie pracuję, to dlaczego zmienna m_value obiektu się zmienia, ale wskaźnik zwraca już adres innego obiektu (kopi?).
Jeżeli dam wzrócenie przez referencję, to wszystko działa jak zaplanowano:
C/C++
Calc & add( int value ) { m_value += value; return * this; }
Calc & sub( int value ) { m_value -= value; return * this; }
Ale nie rozumiem, czemu obiekt zostaje zmieniony, ale return this nie wskazuje na ten obiekt.
P-151842
arciobus
» 2016-09-19 21:46:50
return * this;

Nie zwracasz tutaj wskaźnika, tylko obiekt na który wskazuje. Można go zwrócić tutaj na dwa sposoby. Przez referencję (adres pamięci obiektu) lub przez wartość (obiekt zostanie skopiowany). Adresu kopiowanego obiektu nie można pobrać, za pomocą zwykłej referencji, gdyż jest to wartość tymczasowa, która istnieje tylko przez krótki moment działania programu. Na przykładzie:

C/C++
class Calc
{
private:
    int m_value;
   
public:
    Calc() { m_value = 0; }
    Calc add( int value ) { m_value += value; return * this; }
    Calc & add_ref( int value ) { m_value += value; return * this; }
    Calc sub( int value ) { m_value -= value; return * this; }
   
    int getValue() { return m_value; }
};


int main()
{
    Calc calc;
    //std::cout << &calc.add(0) << '\n'; Błąd kompilacji, pobieranie adresu obiektu tymczasowego
    std::cout << & calc.add_ref( 0 ) << '\n'; //poprawne wypisanie adresu
}
P-151843
pozdro600
Temat założony przez niniejszego użytkownika
» 2016-09-19 21:58:42
Mój, błąd, oczywiście zwracam obiekt, a nie wskaźnik na obiekt. Czyli kopia obiektu następuje dopiero w linijce:
return * this
?
Bo operacja dodawania jest wykonywana na oryginale.
Trochę to dziwne, bo przy normalnych funkcjach kopia zmiennych występuje przy wywołaniu funkcji...
P-151844
pekfos
» 2016-09-19 22:00:25
Trochę to dziwne, bo przy normalnych funkcjach kopia zmiennych występuje przy wywołaniu funkcji...
A co to, jak funkcja zwraca obiekt przez wartość, to już nie jest normalna? Obiekt przez wartość można tylko przekazywać w argumencie?
P-151845
mateczek
» 2016-09-20 01:44:54
Operacja dodawania jest na oryginale, ale w momencie zwracania przez wartość jest tworzony obiekt tymczasowy. Zwracanie przez metodę "*this"
to patent by po wywołaniu raz metody móc na obiekcie zrobić coś ponownie. I wtedy należy raczej zwracać przez referencję. 
C/C++
#include <iostream>

using namespace std;
struct counter
{
    int i;
    counter increment_1() //1 - pierwsza funkcja inkrementująca - zwraca przez wartość
    {
        ++i;
        return * this;
       
    }
    counter & increment_2() //2 - druga funkcja inrementująca - zwraca referencje
    {
        ++i;
        return * this;
       
    }
};
int main()
{
    counter licznik;
    licznik.i = 0;
    cout << "dokokonamy zwiekszenia wartosci przez potrojna inkrementacje = "
    <<( licznik.increment_1().increment_1().increment_1() ).i << endl; //3
    cout << " wyswietlimy zawartość licznika = " << licznik.i << endl;
   
    licznik.i = 0;
    cout << "dokonamy zwiekszenia wartosci przez potrojna inkrementacje = "
    <<( licznik.increment_2().increment_2().increment_2() ).i << endl; //4
   
    cout << "wyświetlimy zawartosc licznika = " << licznik.i << endl;
}
Jakiś czas temu klepnąłem coś takiego. Czy to się nadaje to nie wiem
https://pl.wikibooks.org/wiki/Programowanie_C%2B%2B_Qt4_w_systemie_Gnu-Linux/Referencje_w_C%2B%2B

reasumując dla twojego kodu
C/C++
int main()
{
    Calc calc;
    cout << calc.add( 2 ).add( 3 ).getValue(); //5 zarówno przez wartość jak i przez referencje
   
    cout << calc.getValue();
    // przu zwracaniu przez wartość wynik 2
    // przy zwracaniu przez referencję wynik 5
}
P-151865
pozdro600
Temat założony przez niniejszego użytkownika
» 2016-09-20 08:30:35
Trochę głupio, że tyle już programuję, a nie wiedziałem takich rzeczy. Jestem pod wrażeniem jak to działa. Dzięki za przykład mateczek! Wiele mi wyjaśnił.
P-151868
karambaHZP
» 2016-09-20 10:51:22
P-151869
« 1 »
  Strona 1 z 1