Definicja metody

0

Mam klasę:

class Osoba
{
   public:
      int id;   
      static void wykonaj(int x);
      //inne zmienne i metody
};

void Osoba::wykonaj(int x)
{
   //...
}

Metoda wykonaj jest statyczna, ponieważ muszę się ją wywołać w taki sposób (dla obietu o1 klasy Osoba):

Osoba::wykonaj(o1.id);

Jako, że argumentem tej metody jest zwykła zmienna typu int, nie mogę w żaden sposób skorzystać z innych zmiennych obiektu o1. Czy można w jakiś inny sposób zdefiniować tę metodę (jej argumenty) tak, abym przy takim samym sposobie wywoływania (wymóg zadania) otrzymał wskaźnik do o1?

1

Nie do końca wiem o co Ci chodzi, ale chyba się domyślam..
Jeżeli przekażesz tylko wartość, to właściwie nic Ci to nie pomoże, ale jeżeli przekażesz referencję, to masz adres do obiektu z którego pochodzi ta wartość.. Czyli resztę możesz zrobić dzięki rzutowaniu..

#include<iostream>
using namespace std;
class Osoba{
public:
    int id;
    static Osoba* wykonaj(int &x);
};
Osoba* Osoba::wykonaj(int &x){
    return reinterpret_cast<Osoba*>(&x);
}
int main(){
    Osoba o1,*o2;
    o1.id = 10;
    o2 = Osoba::wykonaj(o1.id);
    cout<<o2->id;
    return 0;
}

Jak widzisz wywołanie zostaję to samo;
Osoba::wykonaj(o1.id);
O to Ci chodziło?

2

kopernik: zdajesz sobie sprawę, że Twój kod działa przez przypadek?

OP: skoro chcesz zdefiniować metodę inaczej, to dlaczego po prostu nie zdefiniujesz jej tak, żeby przyjmowała jako argument wskaźnik/referencję na obiekt tej klasy a nie na int? Jeżeli jednak metoda statyczna ma operować na konkretnym obiekcie, to po co ma być statyczna?

0

@kopernik
Tak, dokładnie o to:) Ogromne dzięki.

@Endrju
W moim obecnym położeniu ważne, że działa. A to że definiuję ją na zmienną id wynika z wymogów zadania. W treści mam, że metoda będzie wywoływana w taki, a nie inny sposób, a ja do tego dopisuję klasy/metody tak, aby to wywołanie działało prawidłowo. Metoda jest statyczna dlatego, że to chyba jedyna możliwość (jaką znam), taka, żeby nie wymagała podawania obiektu przy wywołaniu (którego sposób, jak napisałem wyżej, mam narzucony).

0

Mnie się wydaje że autorowi zadania chodziło raczej o jakąś implementację Service Locatora a nie o takiego hacka jak tutaj przedstawiony, chociaż muszę przyznać że jest dość ciekawy ;)

0

tak dla jasności:

o2 = Osoba::wykonaj(o1.id); (o1.id==10)
nie jest jednoznaczne z:
o2 = Osoba::wykonaj(10);

ja bym proponował mimo wszystko statyczną mapę int na Osoba* lub ustawianie z automatu id jako (int)(this)

0

@krwq
Dzięki, też to właśnie zauważyłem, ale po cichu liczę, że nie będzie testów dla takiego przypadku:) Jak coś to zmienię.

Ogólnie, w przykładowym wejściu, metoda ta jest wywoływana na 3 różne sposoby:

o1.wykonaj();
Osoba::wykonaj(o2.id);
o3->wykonaj(14);

I, jako że nic innego nie przyszło mi do głowy, po prostu przeciążam 3 razy metodę wykonaj tak, żeby działała dla każdego przypadku.

Plus, mam jeszcze jedno pytanie. Normalnie tworzę obiekty w taki sposób:

Osoba o1(printfId);   //Gdzie argumentem jest wskaźnik do jakiejś wcześniej zdefiniowanej funkcji

Ale w jednym, z przykładowych wejść pojawia się coś takiego:

Osoba o10[10];
o10[2].wykonaj();   //A tak jest wywoływana metoda dla tego obiektu

Co to w ogóle może być? Jakaś tablica obiektów? Jak dla czegoś takiego ma wyglądać konstruktor?

1

Tak, to jest tablica obiektów. Gdyby konstruktor miał taką deklarację :

Osoba(int i);

Mógłbyś na przykład tak zainicjować obiekty:

Osoba o[10]{1,2,3,4,5,6,7,8,9,10};

W przypadku:

o3->wykonaj(14);
o1.wykonaj();

Nie ma potrzeby żeby metoda była statyczna. Jest tylko różnica w tworzeniu obiektów.
-> służy do pokazywania na metody jeżeli jest to wskaźnik bądź obiekt tworzony na stercie za pomocą wskaźnika i operatora new. A kropka służy do pokazywania, jeżeli obiekt znajduje się na stosie..

1

Nie za bardzo rozumiem o co Ci chodzi.. Może to troszkę rozjaśni..

#include<iostream>
using namespace std;
class Osoba{
public:
    int id;
    Osoba(int i){ id=i;}
    static Osoba* wykonaj(int &x);
    Osoba* wykonaj(){
        return this;
    }
};
Osoba* Osoba::wykonaj(int &x){
    return reinterpret_cast<Osoba*>(&x);
}
int main(){
    Osoba o[10]={1,2,3,4,5,6,7,8,9,10};
    cout << o[9].id << endl;

    Osoba* ws = Osoba::wykonaj(o[8].id);
    cout<< ws->id <<endl;

    Osoba* w = o[1].wykonaj();
    cout << w->id;
    return 0;
}

Wklej tu może całą treść zadania.. Może źle do czegoś podchodzimy..

A tak w ogóle za pomocą rzutowania i wskaźników można zrobić na prawdę dużo nietypowych rzeczy (można za głowę się złapać:) )

class Osoba{
    int id;
public:
    int GetId(){
        return id;
    }
    Osoba(int i):id(i){}
    static Osoba* wykonaj(int &x){
        return reinterpret_cast<Osoba*>(&x);
    }
    Osoba* wykonaj(){
        return this;
    }
};
int main(){
    Osoba o(5);
    Osoba* p = Osoba::wykonaj(*(reinterpret_cast<int*>(&o)));
    cout<<p->GetId();
    return 0;
}

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