Wywołanie konstruktora a dziedziczenie

Wywołanie konstruktora a dziedziczenie
fasadin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4883
0

Mam dwie klasy

Kopiuj
class Character

oraz

Kopiuj
class Player : public Character

w Player mialem jeden konstruktor (tylko jeden)

Kopiuj
Player::Player(const std::string& name, const std::string& avatarPath) :
Character(name, avatarPath)
{
} 

ale teraz potrzebuje zrobic drugi. Moze nie tyle co drugi co potrzebuje usunac name z pierwszego (drugi nie musi istniec)
wiec zrobilem

Kopiuj
Player::Player(const std::string& avatarPath)
{
	
} 

no i pokazuje, ze Character nie ma domyslnego konstruktora (no bo ma tylko jeden zdefiniowany). Co oryginalnie chcialem zrobic to cos takiego

Kopiuj
Player::Player(const std::string& avatarPath)
{
	std::string name = GetNameFromFile();
	this->Player(name, avatarPath);
}  

no ale to nie zadziala (bo nie ma konstruktora domyslnego w character) wiec pierwsza mysl rozwiazania jest taka by zdefiniowac go i zrobic pustym.

PYTANIE. Czy jest ok, ze wywolaja sie dwa konstruktory klasy bazowej podczas tworzenia obiektu? Wydaje mi sie, ze tak, ale chcialem sie upewnic, a nie moglem nic znalezc w googlach

fasadin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4883
0

juz widze ze to rozwiazanie nie jest ok bo nie inicjalizuje odpowiednio zmiennych w character mimo ze oba konstruktory tam sa wywolane.

twonek
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2500
1

A nie możesz wywołać konstruktora Character z atrapą (pustym stringiem) w miejscu name, a potem w konstruktorze Player ustawić już pobraną wartość?

EvilOne
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 78
1

jeśli dobrze zrozumiałem, że klasa bazowa koniecznie musi zawierać konstruktor Character(const std::string& name, const std::string& avatarPath), a domyślnie, jeżeli name nie jest podawany chcesz w konstruktorze pobierać z pliku to może dodaj prostą funkcję setName w klasie bazowej, ew. udostępnij tę zmienną składową i do niej przypisz rezultat tej funkcji? Taki szybki przykład:

Kopiuj
class Character
{
public:
	Character(const std::string& name, const std::string& avatarPath) :
		mName{name},
		mAvararPath{avatarPath}
	{

	}

	void setName(const std::string& name)
	{
		mName = name;
	}

private:
	std::string mName;
	std::string mAvararPath;
};

class Player : public Character
{
public:
	Player(const std::string& name, const std::string& avatarPath) :
		Character{name, avatarPath}
	{

	}

	Player(const std::string& avatarPath) :
		Player{"", avatarPath}
	{
		setName(getNameFromFile());
	}

	std::string getNameFromFile() const
	{
		return "name";
	}
};
Sarrus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2512
0

Jawne odpalanie konstruktora wydaje mi się słabym pomysłem. Wydaje się, że powinieneś tam ustawiać po prostu pole name
Co do wywołania bazowego konstruktora, możesz zawsze wywołać ten jedyny z pustym stringiem.
Hmm możesz też chyba zrobić konstruktor chroniony (protected), który nie przyjmuje name na parametrze. Wtedy klasa Character wymaga podania nazwy, ale nie dotyczy to klas dziedziczących.

fasadin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4883
0

rozwiazalem to tak jak @twonek napisal.

Konstruktor nie musial miec tych parametrow, ale po prostu zastanawialem sie czemu tak nie zadziala...

Kopiuj
class Character : public GameObject
{
	public:
	Character(const std::string& cAvatarPath)  : cAvatarPath(avatarPath), mHitpoints(100), mAvatarWidth(359), mAvatarHeight(323)
	{
		mTargetRect.w = GetWidth();
		mTargetRect.h = GetHeight();
		mHpBar.h = cHealthBar;
		mName = "deafult";
	}
}

no i player

Kopiuj
class Player : public Character
{
public:
	Player(const std::string& avatarPath):
	Character(avatarPath)
	{
		mName = LoadPlayerName();
	} 
}

dziala. Jednak nadal mnie nurtuje czemu nie stworzyl sie odpowiednio obiekt?

Sarrus
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2512
2

A nie jest tak, że tworzysz nowy obiekt tym wywołaniem konstruktora? Czyli nie zmieniają się pola obiektu w którym wywołujesz, tylko tworzysz zupełnie nowy, ale nie zapisujesz do żadnej zmiennej więc idzie to w p*du.

fasadin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4883
0

bylo robione mniej wiecej cos takiego
http://ideone.com/vA48ZE

AL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1493
2

@fasadin ale niby jak ma to działać? Wg standardu delegowanie konstruktora działa tylko w liście inicjalizacyjnej i tyle.
http://www.learncpp.com/cpp-tutorial/b-5-delegating-constructors/

Poza tym popatrz na kolejność inicjalizacji klas, podklas itd.

fasadin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4883
0

myslalem ze mozna delegowac w ramach tej samej klasy poza lista inicjalizacyjna. Ale widocznie nie mozna ;)

AL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1493
0

@fasadin jakbyś zrobił tak:

Kopiuj
class Bar: public Foo
{
public:
	Bar(int var):Foo(var){}
	Bar() : Bar(4)
	{	}

};

to powinno iść. Gorzej jak, ta liczba miała być wyliczana w ciele konstruktora delegującego, to wtedy tylko static inline Ci zostało ;)

EDIT: jak oddelegujesz w ciele to stworzysz tymczasowy obiekt na stosie który poleci w diabły po wyjściu ze scope'a.

fasadin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4883
0

wlasnie problem polegal na tym ze ta wartosc jest wyliczana.
wole zmienic architekture niz uzywac static inline ;)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.