Jak rozumieć wskaźnik na instancję tej samej klasy?

0
#include <iostream>
#include <memory>

using namespace std;

class MyClass
{
public:
    MyClass(){
        cout << "Konstruktor" << endl;
    }

    void setFunction(MyClass *ptr){
        parent=ptr;
    }

    MyClass *function(){
        return parent;
    }

private:
    MyClass *parent=nullptr;
};

int main()
{
    MyClass *cl = new MyClass;

    cout << cl << endl;
    cl->setFunction(cl);
    cout << cl->function() << endl;

    return 0;
}

Czy ktoś wyjaśniłby mi ten kod co ja tutaj zrobiłem ? Czy mam rozumieć to tak, że zrobiłem wskaźnik który może zaadresować obiekt pokazujący na "sam siebie" ?

1

To zwykły wskaźnik, o co chodzi?

1

W nowym C++ powinieneś sprawdzić smart pointery - spróbuj zrobić kod z nimi

0
kq napisał(a):

To zwykły wskaźnik, o co chodzi?

chodzi o to, że zrobiłem klasę MyClass, a w tej klasie jest funkcja która przyjmuje również wskaźnik MyClass

void setFunction(MyClass *ptr)

więc jeżeli tak, to jak mam to rozumieć ? że jakby adresowała sama siebie ?

3

Masz dwa wskaźniki które patrzą na obiekt MyClass.

3

MyClass *cl = new MyClass; tworzy obiekt klasy MyClass, który nie ma rodzica (jest null_ptr). Następnie wywołujesz cl->setFunction(cl) (choć to powinno się nazywać setParent) i to w rzeczy samej ustawia rodzica obiektu cl na samego siebie. Logicznie trochę bez sensu, przydałby się tam test if (this == ptr), żeby wyeliminować takie zachowanie, czyli rzucić wyjątkiem, zwrócić kod błędu, etc.

3

Co do wątku, ciezko "zrozumieć" jak tyle lat trenowało się umyusł na "jestem guru i przyjmowac wiedzy nie potrzebuję"
To sie nazywa wdrukowanie. Kiepsko widzę

zkubinski napisał(a):

, a w tej klasie jest funkcja która przyjmuje również wskaźnik MyClass

void setFunction(MyClass *ptr)

więc jeżeli tak, to jak mam to rozumieć ? że jakby adresowała sama siebie ?

Mam w neuronach ułożone rozróżnienie klasa a obiekt klasy / instancja ? Chyba nie, jesli widzisz w tym "samą siebie"

metodę ze wskaźnikiem na inny obiekt tej samej klasy można zaakceptować jak "integracyjną"
"zrób coś, co zintegruje stan mój z tamtym", np operator dodawania w językach, które nie mają nazywanych (forsowanych) operatorów

I zarazem, wracając do C/C++, tu jest duży problem.
We wszystkich racjonalnych użyciach tego wzorca jak by dopuszczał jedynie
void setFunction(const MyClass *ptr)
aby wyrazić "tego drugiego obiektu nie zmieniam"

0
jvoytech napisał(a):

MyClass *cl = new MyClass; tworzy obiekt klasy MyClass, który nie ma rodzica (jest null_ptr). Następnie wywołujesz cl->setFunction(cl) (choć to powinno się nazywać setParent) i to w rzeczy samej ustawia rodzica obiektu cl na samego siebie. Logicznie trochę bez sensu, przydałby się tam test if (this == ptr), żeby wyeliminować takie zachowanie, czyli rzucić wyjątkiem, zwrócić kod błędu, etc.

Twoja odpowiedź dla mnie jest najbardziej sensowna. Chciałbym zapytać dlaczego uważasz, że wskazywanie na samego siebie jest bez sensu ? Bo ja to rozumiem tak:

  1. Powołuję do życia obiekt MyClass *cl = new MyClass; który nie ma nazwy ale został nadany mu adres i zawiera wszystkie składowe tej klasy. Jedną z tych składowych jest funkcja,
void setFunction(MyClass *ptr)
{
  parent=ptr;
}

która przyjmuje wskaźnik na obiekty tej samej klasy. Czyli Jak zostanie powołany do życia ten obiekt wraz ze składowymi tej klasy, to funkcja przyjmująca argument obiektu MyClass wykona jakby kopię samej siebie bez adresu i jak ustawię tam adres to ten adres będzie wskazywał na samego siebie - bo inaczej jak to rozumieć ?

  1. Użyłeś fajnego określenia rodzic czyli ten obiekt mogę wykorzystać do wskazania obiektom potomnym kto jest ich rodzicem - czy dobrze pomyślę, że to bardzo może się przydać przy dziedziczeniu ? Bo obiekty potomne, to te które dziedziczą po klasie np abstrakcyjnej ?
2

@zkubinski:

Rodzica się dostaje jakiś czas po urodzeniu ? Kurczę, muszę zweryfikowac swoja wiedzę z biologii
(hint: rodzica się przypisuje w kosntruktorze)

zkubinski napisał(a):

Bo obiekty potomne, to te które dziedziczą po klasie np abstrakcyjnej ?

Wiesz co jest najgorsze? Pozór wiedzy. Jest o wiele, wiele gorsza od zupełnej niewiedzy.

Nie podejmuję się odpowiedzieć szczegółowo na kolejne zdania. Nie jaram tego co ty.

3
zkubinski napisał(a):
  1. Powołuję do życia obiekt MyClass *cl = new MyClass; który nie ma nazwy ale został nadany mu adres i zawiera wszystkie składowe tej klasy. Jedną z tych składowych jest funkcja,
void setFunction(MyClass *ptr)
{
  parent=ptr;
}

która przyjmuje wskaźnik na obiekty tej samej klasy. Czyli Jak zostanie powołany do życia ten obiekt wraz ze składowymi tej klasy, to funkcja przyjmująca argument obiektu MyClass wykona jakby kopię samej siebie bez adresu i jak ustawię tam adres to ten adres będzie wskazywał na samego siebie - bo inaczej jak to rozumieć ?

Instancja klasy (obiekt) nie zawiera funkcji składowych. W momencie tworzenia obiektu NIE TWORZĄ się kopie funkcji składowych!

Funkcje składowe dostają jako niejawny argument wywołania wskaźnik na obiekt dla kórego zostały wywołane.

Pisane bez sprawdzania więc mogą być błędy:

class Foo {
public:
// publiczne tylko w celach demonstracyjnych !
  int value;   
  
  void set_value(int v);
};

void set_value(Foo *obj, int v)
{
  obj->value = v;
}

void Foo::set_value(int v)
{
  value = v;
  
  // w tym kontekście jest to równoważne
  this->value = v;

  // this jest wskaźnikiem na obiekt, dla którego wywołano funkcję składową
}


int main()
{
  Foo f;
  f.set_value(10);
  set_value(&f, 20);
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1