komunikacja między obiektami woki_toki

0

Cześć, mam taki problem:
mam klasę woki_toki, której celem jest komunikowanie się z innymi "wiki_tokami" :) -> tak jak zwykła zabawka dla dzieci.
Czyli klasa ma odbiornik i nadajnik. No i mam pytanie jak to zrobić, żeby jakiś obiekt typu woki_toki miał możliwość takiej komunikacji -> tzn. żeby mógł przyjąć jakiś sygnał oraz jakiś sygnał zwrócić do innych obiektów, które są z nim połączone?
Pobieranie danych do klasy można zrobić funkcją pobierz_text(string text).
Zastanawiam się jednak jak klasa może przekazywać sygnał do innych obiektów?

Ogólnie to widzę jedną możliwość, ale nie wiem czy jest ona poprawna -> stworzyć wewnątrz klasy tablicę wskaźników typu tej klasy czyli:

class woki_toki
{
woki_toki* connect;
int ilosc_polaczen;
public:
void pobierz_text(string in);
void wysilij_text(string out);
}

void woki_toki::wyslij_text(string out){
for(int i=0; i<ilosc_polaczen;i++)
connect->pobierz_text(out);
}
}

a następnie przy chęci wysłania jakiejś wiadomości do pozostałych "użytkowników" wywołać funkcję wyslij_text, która zostanie przesłana do odpowiednich innych obiektów...
A jak zrobić, gdy połączenie miałoby być z innym obiektem? np. chciałbym połączyć się między typem pilot_do_TV a obiektem typu telewizor? Czyli jak wyprowadzać na zewnątrz klasy pilot_do_TV sygnał?

z góry dzięki za pomoc!
pozdrawiam

Nie wiem jednak czy to jest dobra metoda - czy są inne opcje?

0

Stwórz obiekt, który będzie takim swoistym BTSem/stacją przekaźnikową. W niej obiekty nadawczo/odbiorcze będą rejestrowały swoją obecność i przez nią lub bezpośrednio będą przesyłać dane do innych obiektów.

0
stalk3r napisał(a)

Stwórz obiekt, który będzie takim swoistym BTSem/stacją przekaźnikową. W niej obiekty nadawczo/odbiorcze będą rejestrowały swoją obecność i przez nią lub bezpośrednio będą przesyłać dane do innych obiektów.

Ale jak ona ma pobierać dane od tych woki_toki? tzn. jak one mają ten sygnał przekazywać na zewnątrz - do tej "stacji"? I jak to ma się do "enkapsulacji"?

0

Np. poprzez przekazywanie referencji do przekaźnika. Woki_toki może przechowywać referencję do 'zalogowanego' BTSa i wywoływać np. metodę tego BTSa WyslijWiadomosc(id odbiorcy, text), który to prześle wiadomość do danego urządzenia (w sensie wywoła metodę tego obiektu bo posiada referencję), lub BTS zwróci nadawcy referencję do odbiorcy i ten (nadawca) bezpośrednio wywoła funkcje odbiorcy. Tysiące możliwości...

0

Przepraszam, że tak męczę, ale czy mógłby ktoś sprawdzić czy poniższy kod jest tym o co chodziło? Dopiero się uczę i boję się tego co robię :D -> jakby co to kod się kompiluje i działa -> bardziej chodzi mi o poprawność zapisu, optymalność, lepsze rozwiązanie etc.
Jeśli dobrze zrozumiałem chodziło o użycie referencji w funkcji prawda?

Mam jeszcze pytanie czy da się to zrobić jakoś bardziej optymalnie?
Czy można (czy nie lepiej by było) do tego zadania użyć np. wskaźnika, który byłby zapisany wewnątrz klasy woki_toki i bezpośrednio zapisywałby dane do przekaźnika?

mój kod to:

//klasa woki_toki
class woki_toki
{
public:
	void get_text(przekaznik x);
	void send_text(string txt, przekaznik& x);
	przekaznik* przek;

private:
	string text_in;
	string text_out;
};
void woki_toki::get_text(przekaznik x)
{
	text_in = x.text;
	cout << text_in << endl;
}
void woki_toki::send_text(string txt, przekaznik& x)
{
	x.text = txt;
}

//przekaźnik
class przekaznik
{
public:
	string text;
};

Z góry bardzo dziękuję za pomoc i rozjaśnienie problemu :)

0

Mam jeszcze jedno pytanie:
Czy da się zapisać wskaźnik do funkcji przesyłanego przez referencję?
tzn. obecnie mam tak:

przekaznik * przek;
void set_przekaz(przekaznik * x)
{
przek = x;
}

ale przez to wywołując taką funkcję muszę robić set_przekaz(&obiekt); //i może jest bezpieczniej ale mniej wygodnie z tak oczywistą funkcją (wiadomo, że będzie bazować na oryginale).
Dlatego chciałbym, żeby funkcja wyglądała tak:
void set_przekaz(przekaznik& x), żeby móc ją wywoływać bez znaczka "
&
"
ale niestety nie wiem jak zapisać wskaźnik do takiego obiektu <- czy w ogóle jest to możliwe? tzn. jaka będzie analogia do:
przek = x; //?

0
DarkMax napisał(a)

Czy da się zapisać wskaźnik do funkcji przesyłanego przez referencję?

Oczywiście chodziło o: "Czy da się **wkopiować **wskaźnik do obiektu przesyłanego przez referencję"

0
przekaznik &przek;
void set_przekaz(przekaznik &x)
{
   przek = x;
}

```cpp przekaznik *przek; void set_przekaz(przekaznik &x) { *przek = x; } ```
```cpp przekaznik &przek; void set_przekaz(przekaznik *x) { przek = *x; } ```
0
Azarien napisał(a)
przekaznik &przek;
void set_przekaz(przekaznik &x)
{
   przek = x;
}

```cpp przekaznik *przek; void set_przekaz(przekaznik &x) { *przek = x; } ```
```cpp przekaznik &przek; void set_przekaz(przekaznik *x) { przek = *x; } ```

Dzięki wielkie Azarian! Nawet nie wiedziałem, że tak można - czytałem, że referencję można deklarować jedynie z przypisaniem... Teraz się zastanawiam czy to jest taka właściwość klasy, czy może w książce źle podali :)
Pozdrawiam!

0

Referencja musi być zawsze zainicjowana konkretną wartością, zawsze musi być to przypisanie w którymś miejscu. Jeśli referencja jest (niestatycznym) składnikiem klasy to przypisanie musi być w każdym konstruktorze. Natomiast jeśli referencja jest składnikiem statycznym lub zmienną (lokalną/globalną) to przypisanie musi być w miejscu gdzie definiujemy referencję (definiujemy, nie deklarujemy)

adf88 dzięki za wyjaśnienie. Jednak z tego co napisałeś wychodzi, że ja w swojej klasie muszę mieć konstruktor (którego nie mam) a do tego jest to chyba sprzeczne z tym co napisał Azarien.
Azarien podał przykład, gdzie referencja jest deklarowana (bez przypisania) w ciele klasy a jej wartość jest przypisywana w trakcie wywołania zwykłej składowej funkcji a nie konstruktora.

0

Hey, dzięki wielkie wszystkim za pomoc! Azarien - kompiluje się, tak jak podałeś :).
Niestety pojawił się kolejny problem z tym związany. Po uruchomieniu programu, wpisaniu text-u wyskakuje mi komunikat:
"Unhanded exception at 0x00412b1b in ćwiczenia.exe: 0xC0000005:
Access violation reading location 0xcccccce4".
Czy ktoś wie o co chodzi? :/ Naruszenie pamięci?!?

Mój kod nie jest długi więc pozwolę sobie go ponownie zamieścić (zmodyfikowany o w/w opcje):

void main()
{
	przekaznik one;
	przekaznik two;

	woki_toki woki1;
	woki_toki woki2;
	woki_toki woki3;

	string text1, text2, text3;
	cout << "wpisz text" << endl;
	cin >> text1;
	cout << "again:" << endl;
	cin >> text2;
	cout << "odpowiedź" << endl;
	cin >> text3;
	cout << endl;

	woki1.set_przek(one);
	woki2.set_przek(two);
	//woki3.set_przek(one);

	woki1.send_text(text1);
	woki2.send_text(text2);
	woki3.send_text(text3);
	woki1.get_text();
	woki2.get_text();
	woki3.get_text();

	_getch();
}
class woki_toki
{
public:
	void get_text();
	void send_text(string txt);
	przekaznik* przek;
	void set_przek(const przekaznik& x);

private:
	string text_in;
	string text_out;
};
void woki_toki::get_text()
{
	text_in = przek -> text;
	cout << text_in << endl;
}

void woki_toki::set_przek(const przekaznik& x)
{
	*przek = x;
}

void woki_toki::send_text(string txt)
{
	przek -> text = txt;
}
class przekaznik
{
public:
	string text;
};

Bardzo proszę o kolejną pomoc!

0

Aha, i jakby co to gdy przekazuję do funkcji set_przek wskaźnik a nie referencję to wszystko działa prawidłowo!
Czyli jeśli jest tak:

void woki_toki::set_przek(const przekaznik* x) //const dałem żeby sprawdzić czy coś pomoże - nie pomogło!
{
        przek = x;
}

W kodzie jedna linijka jest ujęta w komentarz, ale gdy się ją uwzględni to program również się zawiesza :/
Bardzo, bardzo proszę o pomoc :)

0

Jest takie magiczne narzędzie, co niektórzy nazywają go debuggerem - jest on taki mądry, że sam z siebie, bez większego zachęcania, pokaże co jest nie tak z kodem. A tak na poważnie to polecam rozpocząć od jakiś podstaw Hello World, bo widzę, że nie tylko brak tutaj 'pomysłu' na rozwiązania zadania, ale i elementarnej wiedzy z c++

0
void woki_toki::set_przek(const przekaznik& x)
{
        *przek = x;
}

A wiesz co oznacza ta * przed przek? Jeśli nigdzie nie powiesz najpierw, gdzie przek ma wskazywać, to najprawdopodobniej będzie wskazywał na śmieci, czyli na pamięć nie należącą do Twojego programu (to nawet lepiej, bo gdyby jakimś trafem wskazywał na pamięć przydzieloną Twojemu programowi, to już katastrofa). Albo najpierw przydzielasz pamięć obiektowi typu przekaznik (pole *przek) i dopiero wtedy kopiujesz te dane to Twojego pola w klasie woki_toki, albo robisz tak:

przek = &x;

tylko wtedy musisz pamiętać, że jak zmienna, którą przekazałeś do metody set_przek wyjdzie poza zakres widoczności (i będzie to zmienna lokalna na stosie) to wtedy będzie zonk, jak będziesz chciał używać tego wskaźnika.

0
stfu napisał(a)
void woki_toki::set_przek(const przekaznik& x)
{
        *przek = x;
}

A wiesz co oznacza ta * przed przek? Jeśli nigdzie nie powiesz najpierw, gdzie przek ma wskazywać, to najprawdopodobniej będzie wskazywał na śmieci, czyli na pamięć nie należącą do Twojego programu (to nawet lepiej, bo gdyby jakimś trafem wskazywał na pamięć przydzieloną Twojemu programowi, to już katastrofa). Albo najpierw przydzielasz pamięć obiektowi typu przekaznik (pole *przek) i dopiero wtedy kopiujesz te dane to Twojego pola w klasie woki_toki, albo robisz tak:

przek = &x;

tylko wtedy musisz pamiętać, że jak zmienna, którą przekazałeś do metody set_przek wyjdzie poza zakres widoczności (i będzie to zmienna lokalna na stosie) to wtedy będzie zonk, jak będziesz chciał używać tego wskaźnika.

Dzięki Ci wielkie za pomoc.
Mam jednak kilka wątpliwości:

  1. Przed użyciem innych funkcji wywołuję funkcję set_przek -> czyli przypisanie wskaźnikowi poprawnego adresu do danej zmiennej - więc wcześniej mógł pokazywać na śmieci ale później już nie powinien!
  2. Czemu w takim razie wywołanie funkcji z argumentem jako wskaźnik działa poprawnie a z referencją już nie? Jakby wskaźnik miał pokazywać na śmieci w jednym przypadku to w drugim byłoby to analogiczne - a nie jest.
  3. Czyli twierdzisz, że przez przypisaniem do wskaźnika wartości x należałoby dać *przek = 0;? Jak wrócę do domu to to sprawdzę.

pozdrawiam

0

Bazując na kodzie, który podałeś na poprzedniej stronie:

DarkMax napisał(a)
  1. Przed użyciem innych funkcji wywołuję funkcję set_przek -> czyli przypisanie wskaźnikowi poprawnego adresu do danej zmiennej - więc wcześniej mógł pokazywać na śmieci ale później już nie powinien!

set_przek bierze referencję do obiektu typu przekaznik i ten obiekt (wartość) próbuje przepisać w miejsce, na które wskazuje wskaźnik przek, który jest polem w klasie woki_toki. Jednak wcześniej ten wskaźnik wskazuje na dowolne miejsce w pamięci, a nie na swoje, zarezerwowane dla niego, więc następuje naruszenie pamięci. O rozwiązaniu napisałem wcześniej.

DarkMax napisał(a)
  1. Czemu w takim razie wywołanie funkcji z argumentem jako wskaźnik działa poprawnie a z referencją już nie? Jakby wskaźnik miał pokazywać na śmieci w jednym przypadku to w drugim byłoby to analogiczne - a nie jest.

Przekazując wskaźnik do metody przekazujesz adres tego obiektu. Czyli tak naprawdę kopię ADRESU, w którym znajduje się ten obiekt. Skoro tak, to wtedy przypisanie przek = x oznacza: "niech teraz wskaźnik przek wskazuje na to samo, na co wskazuje wskaźnik x", czyli niech wskazują na ten sam ADRES. Tutaj to będzie ok, dopóki ten adres nie stanie się śmieciem.

DarkMax napisał(a)
  1. Czyli twierdzisz, że przez przypisaniem do wskaźnika wartości x należałoby dać *przek = 0;? Jak wrócę do domu to to sprawdzę.

Katastrofa wtedy murowana, bo przek wskazuje na śmieci. Naucz się jak przydzielać pamięć dynamicznie. Podpowiedź: operator new. Najlepiej coś takiego zrobić w konstruktorze, którego nomen omen nie masz (to znaczy masz, ale jest domyślny).

0
stfu napisał(a)

Bazując na kodzie, który podałeś na poprzedniej stronie:

DarkMax napisał(a)
  1. Przed użyciem innych funkcji wywołuję funkcję set_przek -> czyli przypisanie wskaźnikowi poprawnego adresu do danej zmiennej - więc wcześniej mógł pokazywać na śmieci ale później już nie powinien!

set_przek bierze referencję do obiektu typu przekaznik i ten obiekt (wartość) próbuje przepisać w miejsce, na które wskazuje wskaźnik przek, który jest polem w klasie woki_toki. Jednak wcześniej ten wskaźnik wskazuje na dowolne miejsce w pamięci, a nie na swoje, zarezerwowane dla niego, więc następuje naruszenie pamięci. O rozwiązaniu napisałem wcześniej.

DarkMax napisał(a)
  1. Czemu w takim razie wywołanie funkcji z argumentem jako wskaźnik działa poprawnie a z referencją już nie? Jakby wskaźnik miał pokazywać na śmieci w jednym przypadku to w drugim byłoby to analogiczne - a nie jest.

Przekazując wskaźnik do metody przekazujesz adres tego obiektu. Czyli tak naprawdę kopię ADRESU, w którym znajduje się ten obiekt. Skoro tak, to wtedy przypisanie przek = x oznacza: "niech teraz wskaźnik przek wskazuje na to samo, na co wskazuje wskaźnik x", czyli niech wskazują na ten sam ADRES. Tutaj to będzie ok, dopóki ten adres nie stanie się śmieciem.

DarkMax napisał(a)
  1. Czyli twierdzisz, że przez przypisaniem do wskaźnika wartości x należałoby dać *przek = 0;? Jak wrócę do domu to to sprawdzę.

Katastrofa wtedy murowana, bo przek wskazuje na śmieci. Naucz się jak przydzielać pamięć dynamicznie. Podpowiedź: operator new. Najlepiej coś takiego zrobić w konstruktorze, którego nomen omen nie masz (to znaczy masz, ale jest domyślny).

Dziękuję Ci ślicznie! Działa!!!
A co ważniejsze już zrozumiałem :)
Nie chcę na nikogo zwalać, ale poprzedni sposób zaczerpnąłem od Azarien-a :P - który oczywiście chciał dobrze :)
Jeszcze raz dziękuję wam obu ślicznie! W sumie to wam trzem - chociaż ostatnia wypowiedź stalk3r-a nie była zbyt miła :/ - chyba zapomniał, że sam kiedyś zaczynał, a nie każdy tak szybko łapie jak on...
pozdrawiam!

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