Dziedziczenie po klasie szablonowej

0

Witam, mam problem z szablonami a mianowicie chodzi mi o unresolved external symbol
przechodzimy do kodu jak to wygląda itp...
mam szablon


namespace KOD
{
	template <class TObj>
	class IWorld
	{
		std::unordered_map<size_t, std::shared_ptr<TObj>> m_objectsList;
	public:
		IWorld() = default;
		virtual ~IWorld() = default;
		virtual void addGameObject(std::shared_ptr<TObj> obj) = 0 ;
		virtual void removeGameObject(std::shared_ptr<TObj> obj) = 0;
		virtual void removeGameObject(size_t uid) = 0;
		virtual void update(const size_t dt) = 0;
	};
}

po którym dziedziczy oraz zarazem implementuje virtualne metody, pytanie numer jeden skoro szablon ma funkcje wirtualne to implementacja powinna nadpisać funkcje klasy bazowej i to robi ale dlaczego w tym przypadku implementacja misi być w pliku .h


namespace KOD
{
	class World :
		public IWorld<KOD::GameObject>
	{
		std::unordered_map<size_t, std::shared_ptr<KOD::GameObject>> m_gameObjects;

		void removaAllObjects() { // kod metody }
	public:
		QuadTree<KOD::GameObject> m_qTree;
		World() = delete;

		World(BoundingBox qTreeArea)
			:m_qTree(KOD::QuadTree<KOD::GameObject>(qTreeArea.m_position, qTreeArea.m_size, 0)) { // ctora metody }

		virtual ~World()
        { 
            // kod metody
        }

		virtual void addGameObject(std::shared_ptr<KOD::GameObject> obj)
		{
			// kod metody
		}

		virtual void removeGameObject(std::shared_ptr<KOD::GameObject> obj)
		{
			// kod metody
		}

		virtual void removeGameObject(size_t uid)
		{
			// kod metody
		}

		virtual void update(const size_t dt) override 
        {
            // kod metody
        };
		std::unordered_map<size_t, std::shared_ptr<KOD::GameObject>>& getObjectList()
		{
			// kod metody;
		}
	};
}

idąc dalej
mam taką klasę gdzie IObject, IDrawable, IUpdatable oraz Collider to zwykłe klasy virtualne (interfejsy które nie są szablonami) wiec teoretycznie nie jest wymagane aby implementacja interfejsów była w pliku .h (przypadek updateBoundingBox oraz getFlags ma implemetacje w pliku .cpp)

namespace KOD
{
	struct GameObjectFlags
	{
		bool isCollsionable = false;
	};

	class GameObject
		:public KOD::IObject, public KOD::IDrawable, public KOD::IUpdatable, public KOD::Collider
	{
		BoundingBox m_boundingBox;;
	protected:
		GameObjectFlags m_flags;
	public:
		GameObject() = default;
		GameObject(GameObjectFlags flags) :m_flags(flags) {};
		virtual void draw(sf::RenderWindow& window) override {};
		virtual void update(const size_t dt) override {};
		virtual void onCollision() override {};
		BoundingBox& getBoundingBox() { return m_boundingBox; };
		void updateBoundingBox(sf::Vector2f pos, sf::Vector2f size); // in .cpp file
		BoundingBox& getFlags(); // in .cpp file
	};
}

klasa Player

class Player
  :public KOD::GameObject
{
	sf::RectangleShape rect;
	void input(const size_t dt);
public:
	Player();
	virtual ~Player() = default;
	virtual void draw(sf::RenderWindow& window) override;
	virtual void update(const size_t dt) override;
	void setPosition(sf::Vector2f pos);
	sf::Vector2f getPosition();
};

i teraz pytanie najważniejsze dlaczego gdy implementacja updateBoundingBox oraz getFlags jest w pliku .c to kompilacja nie przechodzi i dostaję a gdzy jest w pliku .h to nie ma problemu

LNK2001	unresolved external symbol "public: void __cdecl KOD::GameObject::updateBoundingBox(class sf::Vector2<float>,class sf::Vector2<float>)" (?updateBoundingBox@GameObject@KOD@@QEAAXV?$Vector2@M@sf@@0@Z)	TestingApp	D:\dev\SFML_Game_Engine\App\Player.obj	1	

LNK2001	unresolved external symbol "public: struct KOD::BoundingBox & __cdecl KOD::GameObject::getFlags(void)" (?getFlags@GameObject@KOD@@QEAAAEAUBoundingBox@2@XZ)	TestingApp	D:\dev\SFML_Game_Engine\App\TestGameState.obj	1	
1

dlaczego w tym przypadku implementacja misi być w pliku .h

Nie musi. Klasa World nie jest klasą szablonową (template class), więc implementacja metod może być w pliku cpp.

updateBoundingBox oraz getFlags jest w pliku .c

Translation unit C++ powinien mieć rozszerzenie cpp.

Wygląda to tak jakbyś miał problem z linkowaniem. Żeby Ci pomóc musiałbyś przedstawić jakie masz moduły (projekty w VS), jakie pliki wchodzą do modułów, czy są w ogóle kompilowane.

0
mwl4 napisał(a):

dlaczego w tym przypadku implementacja misi być w pliku .h

Nie musi. Klasa World nie jest klasą szablonową (template class), więc implementacja metod może być w pliku cpp.

updateBoundingBox oraz getFlags jest w pliku .c

Translation unit C++ powinien mieć rozszerzenie cpp.

Wygląda to tak jakbyś miał problem z linkowaniem. Żeby Ci pomóc musiałbyś przedstawić jakie masz moduły (projekty w VS), jakie pliki wchodzą do modułów, czy są w ogóle kompilowane.

https://github.com/ArturKnopik/SFML_Game_Engine
nie wiem czy cały kod pomoże ale wysyłam zapobiegawczo

0
class KOD::GameObject;
class World :
		public IWorld<KOD::GameObject>
0
_13th_Dragon napisał(a):
class KOD::GameObject;
class World :
		public IWorld<KOD::GameObject>

niestety nie pomogło, wcześniej już tego próbowałem

3

KOD::GameObject masz w module Core i budujesz to do DLL. Próbujesz użyć KOD::GameObject w module TestingApp, który ma referencję do Core. Ale KOD::GameObject nie jest eksportowany z Core.

Żeby to zrobić to musisz użyć czegoś co już definiujesz w KOD_export.h, makra KOD_API.

	class KOD_API GameObject
		:public KOD::IObject, public KOD::IDrawable, public KOD::IUpdatable, public KOD::Collider
	{

https://learn.microsoft.com/en-us/cpp/cpp/using-dllimport-and-dllexport-in-cpp-classes?view=msvc-170

0

totalnie o tym zapomniałem, to rozwiązało mój problem :)

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