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

Jak powinien być zaplanowany taki kod?

Object Storage Arubacloud
0 głosów
286 wizyt
pytanie zadane 21 lipca 2021 w C i C++ przez Daaa22 Dyskutant (8,250 p.)

Kompletnie nie jestem zaznajomiony ze wzorcami projektowymi, mam tylko teorie opanowaną.

Powiedzmy że mamy grę w której jest ekwipunek 4x6, który jest zadeklarowany jako 

Item ekwipunek[4][6];

gdzie Item to jakaś klasa. Ale ten Item może być bronią albo zbroją czyli coś takiego

class Item
{
public:
double cost;
};

class Weapon :public Item
{
public:
double cost;
double damage;
};

class Armor :public Item
{
public:
double cost;
double defence;
};

mam też wskaźnik

Item* it;

który wskazuje na to co aktualnie kliknęliśmy, przykładowo jeżeli kliknę w ekwipunku pole o współrzędnych (2, 3), to 

it = &ekwipunek[1][2];

i teraz mam problem bo mamy funkcje która daje graczowi broń do ręki z ekwipunku

void setWeapon( Weapon weapon )
{
//kod ktory daje graczowi bron, nieistotne w kontekscie mojego pytania
}

ale nie mogę napisać 

setWeapon( it );

ponieważ it to nie Weapon. Jak napisać kod który jest w stanie sprawdzić czy it to broń? Albo jak wy byście rozwiązali tego typu problem?

komentarz 21 lipca 2021 przez Oscar Nałogowiec (29,290 p.)
Po pierwsze nie bardzo możesz utworzyć tablicę w której są obiekty różnych typów. Mogą to być najwyżej wskaźniki.

Ponieważ wszystko co tam masz dziedziczy z Item możesz w tej klasie zamieścić jakiś identyfikator wskazujący jaki jest konkretny obiekt (nadpisywany w klasach pochodnych).

Można też użyć RTTI a w szczególności dynamic_cast.

 

PS. Nie powtarzaj definicji z klasy bazowej w klasach pochodnych bo będziesz miał po dwa tak samo nazywane pola (aczkolwiek rozróżnialne, ale tak na prosto to nowe przesłoni starsze).
komentarz 21 lipca 2021 przez Daaa22 Dyskutant (8,250 p.)

Po pierwsze nie bardzo możesz utworzyć tablicę w której są obiekty różnych typów. Mogą to być najwyżej wskaźniki.

Tak, mój błąd, ale nawet jak są to wskaźniki to nie mogę wywołać funkcji setWeapon( it );

Ponieważ wszystko co tam masz dziedziczy z Item możesz w tej klasie zamieścić jakiś identyfikator wskazujący jaki jest konkretny obiekt (nadpisywany w klasach pochodnych).

Dobrze rozumiem że wtedy każda klasa która dziedziczy z Item musi mieć taką samą liczbę tak samo nazwanych zmiennych? Bo bierzemy Item do ręki, tzn

it = &ekwipunek[x][y];

używamy funkcje

setWeapon( it );

i wewnątrz tej funkcji musi być coś w stylu

if( it -> type == weaponType )
{
playerDamage = it -> damage;
}
else
{
//costam costam
}

ale tu jest problem bo klasa Item nie ma wartości damage. Więc wracając do poprzedniej myśli, każda rzecz która dziedziczy z Item musiałaby mieć wartość damage?

1 odpowiedź

+1 głos
odpowiedź 21 lipca 2021 przez Tomasz Sobczak Bywalec (2,830 p.)
wybrane 21 lipca 2021 przez Daaa22
 
Najlepsza

#include <iostream>

class CT_Item
{
	double cost {};
public:
	CT_Item() = default;
	CT_Item( const double& cost_A ) : cost( cost_A ) {}

	virtual bool isWeapon() {  return false;  };
};
 
class CT_Weapon :public CT_Item
{
	double damage {};
public:
	CT_Weapon() = default;
	CT_Weapon( const CT_Item& item_A ,  const double& damage_A ) : CT_Item( item_A ) , damage( damage_A ) {}	

	bool isWeapon() override {  return true;  };
	double getDamage() { return damage; }
	
};
 
class CT_Armor :public CT_Item
{
	double defence {};
public:	
	CT_Armor() = default;
	CT_Armor( const CT_Item& item_A ,  const double& defence_A ) : CT_Item( item_A ) , defence( defence_A ) {}

	bool isWeapon() override {  return false;  };
};




CT_Item* it { nullptr };

CT_Armor armor1 { { 150.99 } , 20. }; 
CT_Weapon weapon1 { { 22. } , 14.5 };

CT_Item* ekwipunek[4][6] {};

int main()
{
	ekwipunek[ 1 ][ 2 ] = &weapon1;
	ekwipunek[ 2 ][ 2 ]	= &armor1;

	it = ekwipunek[1][2];

	if( dynamic_cast< CT_Weapon* >( it ) ) std::cout << "To bron!" << std::endl;
	else std::cout << "To cos innego." << std::endl; 

	if( ekwipunek[1][2] -> isWeapon() )	std::cout << "( Double check )  To bron!" << std::endl;
	else std::cout << "( Double check ) To cos innego." << std::endl; 

	return 0;
}

Powyżej demonstracja jak można sprawdzić czy to broń.

( ważne ) Możesz do funkcji która przyjmuje jako argument typu CT_Item*  wysłać typ np. CT_Weapon*, ale odwrotnie już nie. 

Jeżeli masz pewność, że to broń to dokonujesz jawnej konwersji poprzez dynamic_cast< CT_Weapon* >( it ) -> getDamage() i otrzymujesz pożądaną wartość. Rezultat rzutowania możesz przypisać sobie do zmiennej typu np. CT_Weapon*.

Podobne pytania

+1 głos
1 odpowiedź 333 wizyt
pytanie zadane 28 marca 2021 w JavaScript przez wsnofi Bywalec (2,680 p.)
+2 głosów
3 odpowiedzi 170 wizyt
pytanie zadane 4 października 2021 w JavaScript przez StaramSieJakMoge Początkujący (310 p.)
0 głosów
1 odpowiedź 144 wizyt
pytanie zadane 2 kwietnia 2017 w C i C++ przez Avernis Nałogowiec (27,400 p.)

92,539 zapytań

141,382 odpowiedzi

319,476 komentarzy

61,928 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!

...