• 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?

0 głosów
72 wizyt
pytanie zadane 21 lipca w C i C++ przez Daaa22 Mądrala (7,300 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 przez Oscar Pasjonat (18,830 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 przez Daaa22 Mądrala (7,300 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 przez Tomasz Sobczak Obywatel (1,670 p.)
wybrane 21 lipca 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ź 94 wizyt
pytanie zadane 28 marca w JavaScript przez wsnofi Bywalec (2,550 p.)
0 głosów
1 odpowiedź 96 wizyt
pytanie zadane 2 kwietnia 2017 w C i C++ przez Avernis Nałogowiec (27,240 p.)
0 głosów
2 odpowiedzi 415 wizyt
pytanie zadane 12 lutego 2017 w C i C++ przez kikosiak Obywatel (1,010 p.)
Porady nie od parady
Nie wiesz jak poprawnie zredagować pytanie lub pragniesz poznać którąś z funkcji forum? Odwiedź podstronę Pomoc (FAQ) dostępną w menu pod ikoną apteczki.FAQ

84,178 zapytań

132,949 odpowiedzi

294,115 komentarzy

55,592 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...