• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Metoda modyfikująca atrybut innej klasy.

Object Storage Arubacloud
0 głosów
268 wizyt
pytanie zadane 6 kwietnia 2017 w C i C++ przez andrzejd Nowicjusz (150 p.)

Witam serdecznie, 

postanowiłem napisać swój pierwszy program obiektowy. Posiada on dwie klasy: Bohater oraz Potwor. Posiadają one po kilka atrybutów oraz funkcję atak, która w założeniu ma modyfikować atrybut należący do klasy przeciwnika (metoda bohatera ma modyfikować HP potwora i na odwrót). Napisałem coś takiego:

#include <iostream>
#include <string>

using namespace std;

class Bohater
{
public:
	int sila;
	string nazwa;
	Bohater(string, int, int); //konstruktor
	int HP;
	void atak(Potwor *);
	void unik();
};

class Potwor
{
public:
	int sila;
	string nazwa;
	Potwor(string, int, int); //konstruktor
	int HP;
	void atak(Bohater *);
};

Bohater::Bohater(string n, int zycie, int s)
{
	nazwa = n;
	sila = s;
	HP = zycie;
}

void Bohater::atak(Potwor * mob)
{
	int wartoscAtaku = 5;
	(*mob).HP = (*mob).HP - wartoscAtaku;
}

Potwor::Potwor(string n, int zycie, int s)
{
	nazwa = n;
	sila = s;
	HP = zycie;
}

void Potwor::atak(Bohater * heros)
{
	int wartoscAtaku = 1;
	(*heros).HP = (*heros).HP - wartoscAtaku;
}

int main()
{
	int akcja;
	Bohater wojownik("Piotr", 100, 5);
	Potwor troll("Shrek", 20, 1);
	cout << "Spotkales na swojej drodze potwora! " << endl;
	while (troll.HP != 0)
	{
		cout << "Czy chcesz go zaatakowac? Wcisnij 1" << endl;
		cin.clear();
		cin.sync();
		cin >> akcja;
		if (akcja == 1)
		{
			wojownik.atak(&troll);
			cout << "zaatakowales trolla! Jego zycie teraz wynosi " << troll.HP << endl;
		}

	}
	cout << "Pokonales go! ";
	system("Pause");
}

Niestety otrzymuję następujące błędy:
1. 'Bohater::atak' : function does not take 1 argument
2. 'void Bohater::atak(Potwor *)' : overloaded member function not found in 'Bohater'
3. syntax error : identifier 'Potwor'

AD 1: Przecież wyraźnie przy definicji funkcji napisałem, że przyjmuje jeden argument, a konkretnie wskaźnik do obiektu klasy Potwor (troll).

AD 2 i 3 - nie mam pojęcia jak to rozgryść :/

Czy ktoś mógłby mi z tym pomóc? To moje pierwsze kroki w programowaniu więc przepraszam, jeśli odpowiedź jest banalna/pytanie głupie.

3 odpowiedzi

+1 głos
odpowiedź 6 kwietnia 2017 przez RobertGardzinski Bywalec (2,460 p.)
wybrane 6 kwietnia 2017 przez andrzejd
 
Najlepsza
1. Po co konstruktory do składników publicznych?

2. Skąd klasa bohater ma wiedzieć o istnieniu klasy Potwor? Zadeklaruj wstępnie tą klasę przed definicją klasy Bohater.
komentarz 6 kwietnia 2017 przez andrzejd Nowicjusz (150 p.)
Dziękuję! Doszedłem do tego, że to może być problem z tym, że klasa bohater nie ma pojęciu o istnieniu klasy Potwor, ponieważ... gdy spróbowałem wykonać atak obiektem klasy Potwor to się udawało! Niemniej, nie wiedziałem, że wystarczy wstępnie zadeklarować klasę Potwor przed klasą Bohater, żeby to zadziałało. Dodałem taką linijkę: class Potwor; i już problemu nie ma.

Jeszcze raz dziękuję!
+1 głos
odpowiedź 6 kwietnia 2017 przez mokrowski Mędrzec (155,460 p.)
#include <iostream>
#include <string>

using namespace std;

// XXX: Deklaracja zapowiadająca by rozwiązać zależności cykliczne
// Potwor<->Bohater
class Potwor;

class Bohater {
  public:
    int sila;
    string nazwa;
    // XXX: Nie chcesz niepotrzebnego kopiowania string'a
    Bohater(const string&, int, int); //konstruktor
    int HP;
    // XXX: W atak() nie modyfikujesz obiektu Bohater. Powinno być const
    void atak(Potwor*) const;
    void unik();
};

class Potwor {
  public:
    int sila;
    string nazwa;
    // XXX: To co wyżej.
    Potwor(const string&, int, int); //konstruktor
    int HP;
    // XXX: Tak samo jak w Bohater...
    void atak(Bohater*) const;
};

// XXX: Inicjalizacja jest wydajniejsza z użyciem listy inicjalizacyjnej
Bohater::Bohater(const string& n, int zycie, int s)
    : sila{s}, nazwa{n}, HP{zycie} { }

void Bohater::atak(Potwor* mob) const {
    int wartoscAtaku = 5;
    // XXX: Czytelniej strzałką.
    mob->HP = mob->HP - wartoscAtaku;
}

// XXX: Lepiej listą.. 
Potwor::Potwor(const string& n, int zycie, int s) 
    : sila{s}, nazwa{n}, HP{zycie} { }

void Potwor::atak(Bohater* heros) const {
    int wartoscAtaku = 1;
    // XXX: Znowu.. lepiej strzałką.
    heros->HP = heros->HP - wartoscAtaku;
}

int main() {
    int akcja;
    Bohater wojownik("Piotr", 100, 5);
    Potwor troll("Shrek", 20, 1);
    cout << "Spotkales na swojej drodze potwora! " << endl;

    while(troll.HP != 0) {
        cout << "Czy chcesz go zaatakowac? Wcisnij 1" << endl;
        cin.clear();
        cin.sync();
        cin >> akcja;

        if(akcja == 1) {
            wojownik.atak(&troll);
            cout << "zaatakowales trolla! Jego zycie teraz wynosi " << troll.HP <<
                 endl;
        }
    }
    cout << "Pokonales go! ";
    // XXX: Jak masz robić taką "popelinę" jak system("pause"), to zmień IDE
    // albo skonfiguruj aby samo zatrzymywało wynik działania programu.
}

 

komentarz 6 kwietnia 2017 przez andrzejd Nowicjusz (150 p.)
Czytałem, że ten system("Pause") to popelina, postaram się tego uniknąć w przyszłości. Poczytam jak to zrobić i dlaczego to jest kiepski sposób na zatrzymanie otwartego programu. (wiem póki co tylko tyle, że jest to coś co jest zależne od systemu, a programy powinny być uniwersalne i tworzy to w jakiś sposób niebezpieczeństwo)

Dziękuję za poprawki w moim programie!
0 głosów
odpowiedź 6 kwietnia 2017 przez .kassad Gaduła (3,420 p.)
Najpierw musisz utworzyć obiekty. Zamiast
Bohater wojownik("Piotr", 100, 5);
powinno być
Bohater wojownik = new Bohater("Piotr", 100, 5);

Myślę, że jak to poprawisz, to reszta błędów powinna zniknąć.

I jeszcze taka wskazówa - zauważ, że dużo rzeczy z klasy Bohater powtarza się w klasie Potwór - warto byś pomyślał o utworzeniu jednej klasy bazowej (np Postać), dzięki czemu unikniesz redundancji kodu.
komentarz 6 kwietnia 2017 przez RobertGardzinski Bywalec (2,460 p.)

Bohater wojownik("Piotr", 100, 5);
powinno być 
Bohater wojownik = new Bohater("Piotr", 100, 5);

Dlaczego? Pierwsza forma jest ok. Tworzy obiekt wojownik.

Druga forma, którą zaproponowałeś to będzie spoko dla wskaźnika. 

komentarz 6 kwietnia 2017 przez andrzejd Nowicjusz (150 p.)
Dziękuję za zainteresowanie, niestety dodanie linijki zaproponowanej przez Ciebie nie pomogło. Niemniej, zrobiłem to co poradził kolega RobertGardzinski i udało się. Dzięki wielkie! :)

Podobne pytania

0 głosów
1 odpowiedź 653 wizyt
pytanie zadane 24 lipca 2018 w C i C++ przez Krutek Początkujący (330 p.)
+1 głos
1 odpowiedź 414 wizyt
+1 głos
1 odpowiedź 4,370 wizyt
pytanie zadane 15 maja 2015 w Java przez nowszy94 Bywalec (2,320 p.)

92,565 zapytań

141,417 odpowiedzi

319,602 komentarzy

61,951 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...