Wyrażenie musi miec typ struct/union - niezrozumiały problem

0

Cześć!

Pisząc projekt spotkałem się z kompletnie niezrozumiałym problemem.
Odwołując się do metody pochodnej wyskakują mi takie błędy:

Błąd C2228 po lewej ".aktualizujPolozenie" musi być typ struct/union
Błąd C2228 po lewej ".aktualizujAnimacje" musi być typ struct/union
Błąd C2664 „void sf::draw(const sf::Vertex *,::size_t,sf::PrimitiveType,const sf::RenderStates &)”: nie można dokonać konwersji argumentu 1 z „cKupacz (__cdecl *)(sf::Vector2u)” do „const sf::Drawable &”

Jest to gra w której dziedziczenie wygląda następująco :

cAnimacja -> cPostac -> cKupacz / cWrog

Wcześniej używałem konstruktora domyślnego ale potrzebuję rozmiaru ekranu w każdej klasie dlatego zdecydowałem się dodać argument do konstruktora.
Po dodaniu konstruktorów, wywaliło mi takie błędy(up) Znalazłem taki temat: most vexing parse.

Mimo wszystko nie rozumiem tego :(
Mógłby mi to ktoś przybliżyć ?

Fragmenty kodów :

//Main.cpp
...
int main()
{
	...

	//----objekty----//
	cKupacz* Kupacz(sf::Vector2u rozmiarOknaGry);
	std::vector<cPostac*> Wrogowie;
	...
	//---konfiguracja---//
	for (int i = 0; i < 1; i++)
	{
		std::unique_ptr<cWrog> w = std::make_unique<cWrog>();
		Wrogowie.reserve(1);
		Wrogowie.emplace_back(w);
	}

	//----petla gry----//
	while (oknoGry.isOpen())
	{
		...

		//----update postaci----//
		Kupacz->aktualizujPolozenie(timer1.getElapsedTime().asSeconds()); // błąd, podkreśla słowo Kupacz - wyrażenie musi mieć typ wskaźnika do klasy
		Kupacz->aktualizujAnimacje(timer1.getElapsedTime().asSeconds());// błąd, podkreśla słowo Kupacz - wyrażenie musi mieć typ wskaźnika do klasy
		
		for (auto& i : Wrogowie)
		{
			i->aktualizujPolozenie(timer1.getElapsedTime().asSeconds()); // <- nie wiem czemu tutaj błędu akurat nie pokazuje skoro u gory pokazuje 
			i->aktualizujAnimacje(timer1.getElapsedTime().asSeconds()); // <- 
		}

		//----rysowanie----//
		oknoGry.clear();
		oknoGry.draw(mapa);
		oknoGry.draw(*Kupacz); // błąd, podkreśla kropkę - żadne wystąpienie elementu funkcja przeciążona "sf::RenderWindow::draw" nie jest zgodne z listą argumentów
                // typy argumentów: (cKupacz *(sf::Vector2u rozmiarOknaGry))
                // typ obiektu to: sf::RenderWindow

		for (auto const & i : Wrogowie)
			oknoGry.draw(*i);

		oknoGry.display();
	}
}
//cPostac.h

class cPostac
	: public sf::Drawable, public cAnimacja
{
public:
	cPostac(sf::Vector2u rozmiarOknaGry);
	~cPostac() = default;

...

public:
	void ustawPozycje(sf::Vector2f wspolrzedne);
	virtual void aktualizujPolozenie(double pobranyCzas) = 0;
	virtual void aktualizujAnimacje(double pobranyCzas) = 0;
	virtual void draw(sf::RenderTarget &target, sf::RenderStates state) const = 0; 
};
//cPostac.cpp
cPostac::cPostac(sf::Vector2u rozmiarOknaGry)
	: rozmiarOknaGry(rozmiarOknaGry) {}
//cKupacz.h
class cKupacz
	: public cPostac
{
public:
	cKupacz(sf::Vector2u rozmiarOknaGry);
	~cKupacz() = default;
...
public:
	void draw(sf::RenderTarget &target, sf::RenderStates state) const override;
	void aktualizujPolozenie(double pobranyCzas) override;
	void aktualizujAnimacje(double pobranyCzas) override;
};

//cKupacz.cpp
cKupacz::cKupacz(sf::Vector2u rozmiarOknaGry)
	: cPostac::cPostac(rozmiarOknaGry)
{
...
}

//cWrog.h
class cWrog
	: public cPostac
{
public:
	cWrog(sf::Vector2u rozmiarOknaGry);
	~cWrog() = default;
...
public:
	void draw(sf::RenderTarget &target, sf::RenderStates state) const override; // ovveride informujmy, że nadpisalismy draw
	void aktualizujPolozenie(double pobranyCzas) override;
	void aktualizujAnimacje(double pobranyCzas) override;
};

//cWrog.cpp
cWrog::cWrog(sf::Vector2u rozmiarOknaGry)
	: cPostac::cPostac(rozmiarOknaGry)
{
...
}
2

to:

cKupacz* Kupacz(sf::Vector2u rozmiarOknaGry);

jest deklaracja funkcji a nie obiektu!
Jak potrzebujesz użyć Kupacz kompilator myśli, że to jest funkcja a nie zmienna, więc narzeka, że po lewej stronie jest coś czego się nie spodziewa.
Powinno być:

cKupacz* Kupacz = new cKupacz(rozmiarOknaGry);
// albo:
auto Kupacz = new cKupacz(rozmiarOknaGry);
// albo:
auto Kupacz = std::make_unique<cKupacz>(rozmiarOknaGry);

Zainteresuj się standardami kodowania, żeby być czytelnym dla innych:

  • nazwa klasy/typu zaczyna się zawsze od dużej litery
  • nazwa zmiennej/pola zaczyna się od małej litery
  • nazwa funkcji/metody zaczyna się od małej litery (tu standardy czasami się różnią, np MS preferuje dużą literę)
  • zawsze camel case
  • w niektórych standardach stosuję się pozostałości notacji węgierskiej (w różnej formie):
    -- klasy są poprzedzone dużą literą "C" np CKopacz
    -- interfejsy mają prefix "I" np IKopacz
    -- pola klasy mają prefix m lub m_
    -- argumenty funkcji/metod prefix a
  • nie pisz funkcji dłuższej niż 10 linii, albo zwiedzającej więcej niż dwie instrukcje sterujące. Dziel to na mniejsze funkcje.

Od pisania kodu po polsku jest gorsze tylko pisanie kodu mieszanką angielskiego i polskiego. Pisz po angielsku.

0
kameleo327 napisał(a):
	std::vector<cPostac*> Wrogowie;
	...
	//---konfiguracja---//
	for (int i = 0; i < 1; i++)
	{
		std::unique_ptr<cWrog> w = std::make_unique<cWrog>();
		Wrogowie.reserve(1);
		Wrogowie.emplace_back(w);
	}

Tworzysz wektor gołych wskaźników i próbujesz wepchnąć do niego smart-pointer. To się nie uda ;)
reserve wywołuj przed pętlą.
emplace_back nie ma zbytnio tutaj sensu. Zamiast tego użyj wrogowie.push_back( std::move( w ) );

MarekR22 napisał(a):

Zainteresuj się standardami kodowania, żeby być czytelnym dla innych:

Standardy są jak tyłek - każdy ma swój ;)

0
tajny_agent napisał(a):

Tworzysz wektor gołych wskaźników i próbujesz wepchnąć do niego smart-pointer. To się nie uda ;)

Więc był to wektor gołych wskaźników czy występowała konwersja ? Jak to działało xD?
Czyli powinno to wyglądać tak ?

std::vector<std::unique_ptr<cPostac>> Wrogowie;
tajny_agent napisał(a):

emplace_back nie ma zbytnio tutaj sensu. Zamiast tego użyj wrogowie.push_back( std::move( w ) );

Rozumiem.

A taki manewr by przeszedł?

Wrogowie.emplace_back(rozmiarOkna);
0
kameleo327 napisał(a):
tajny_agent napisał(a):

Tworzysz wektor gołych wskaźników i próbujesz wepchnąć do niego smart-pointer. To się nie uda ;)

Więc był to wektor gołych wskaźników czy występowała konwersja ? Jak to działało xD?
Czyli powinno to wyglądać tak ?

std::vector<std::unique_ptr<cPostac>> Wrogowie;

A w ogóle kompilowało się? :>

kameleo327 napisał(a):

A taki manewr by przeszedł?

Wrogowie.emplace_back(rozmiarOkna);

wrogowie to wektor obiektów typu unique_ptr<Postac>, więc emplace_back wywoła konstruktor unique_ptr<Postac> a nie Postac.
Najlepiej chyba użyć

wrogowie.push_back( std::make_unique< Postac >( rozmiarOkna ) );

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