Problem z Templatami i stosem

0

Plik HPP

#pragma once

template <typename T>
	class TElem
	{
		T Value;
		char ItemType;
		TElem *Next;
	};

template <typename T>
class MyStack
{
private:
	TElem<T> *Head, *Tail;
public:
	TElem<T> *Pop();
	void Push(T Val);
	void Into(T Val);
	bool IsEmpty();
	TElem<T> *Top();
	MyStack();
	~MyStack();
};

Plik CPP

#include "stdafx.h"
#include <cstdlib>
#include "MyStack.hpp"

template <typename T>
MyStack<T>::MyStack()
{
	Head = Tail = NULL;
}

template <typename T>
MyStack<T>::~MyStack()
{
	while(Head != NULL)
	{
		TElem *El = Head;
		Head = Head->Next;
		free(El);
	}
}

template <typename T>
bool MyStack<T>::IsEmpty()
{
	return Head != NULL;
}

template <typename T>
void MyStack<T>::Push(T A)
{
	TElem *El = new TElem;
	El->a = A;
	El->Next = Head;
	Head = El;

	if(Tail == NULL)
		Tail = Head;
}

template <typename T>
void MyStack<T>::Into(T A)
{
	TElem *El = new TElem;
	El->a = A;
	El->Next = NULL;

	if(Head != NULL)
		Tail->Next = El;
	else
		Head = El;
	Tail = El;
}


template <typename T>
TElem<T> *MyStack<T>::Pop()
{
	TElem *El = Head;
	Head = Head->Next;
	return El;
}

template <typename T>
TElem<T> *MyStack<T>::Top()
{
	return Head;
}
// asdf.cpp : Defines the entry point for the console application.
//

Plik Main

 
#include "stdafx.h"
#include "MyStack.hpp"
#include <iostream>
#include <cstdlib>


int _tmain(int argc, _TCHAR* argv[])
{
	MyStack<char> *st = new MyStack<char>();

	for(int i=0;i<5;++i)
	{
		
	}
	getchar();
	return 0;
}

Błąd: Error 1 error LNK2019: unresolved external symbol "public: __thiscall MyStack<char>::MyStack<char>(void)" (??0?$MyStack@D@@QAE@XZ) referenced in function _wmain

0

Nie rozdzielaj deklaracji i definicji na 2 osobne pliki. Przy szablonach to nie działa. Tzn. powinno działać słowo kluczowe eksport, ale nie wiem które kompilatory to na dzień dzisiejszy obsługują(raczej niewiele).

0

aha, sam VS domyślnie tworzy 2 pliki przy tworzeniu nowej klasy.

0

Bo normalnie tak się powinno robić(tworzyć dwa pliki), ale niestety jeżeli chodzi o szablony to już tak kolorowo nie jest. Nie wiem czy jakiś kompilator poprawnie to obsługuje.

0

WC nie wie że zamierzasz pisać wzorzec klasy.
Cały wzorzec musi być w pliku .h/.hpp
Może za wyjątkiem wyspecjalizowanych metod, czyli pod konkretny typ.

0

no był w HPP.
Ale jednak szablon nie do końca mi odpowiada (chyba).
Jak zrobić, żeby mieć kolejkę różnych typów danych ?
np pierwszy element jest char, a inny to Int , float....

W Delphi można to było zrobić case'm wariantowym. A tu jak ładnie w sposób obiektowy to zrobić ?

1

Użyć biblioteki boost, tam jest taki typ any_coś_tam.
Jak chcesz stworzyć to sam, to prosto nie będzie.
Poza tym w delphi też czegoś takiego od tak nie zrobisz.

0

no wlasnie protsto (ale nie w sposob obiektowy).
Wskaznik na rekord typu wariantowego.

Chcialbym przepisac na C++ pewien program...
Prosto czy nie prosto - jak wiesz to wyjasnij :) Boost odpada - lubie wlasne rozwiazania.

0

Tworzysz klasę o nazwie powiedzmy TAny, która ma wirtualne metody SetInt, GetInt, SetString/GetString itd, wszystkie przy wywołaniu rzucają wyjątek, oraz metodę TypeId;

Tworzysz klasę powiedzmy TAnyInt w której nadpisujesz metody SetInt, GetInt, a metoda TypeId zwraca typeid(int);
Tak samo dla innych typów.

Klasa która jest kolekcją tych TAny nie może trzymać obiektów klasy, tylko wskaźniki na nie. Tworzenie musi odbywać się na zewnątrz:
calss TColection { void Add(TAny *); }

colection.add(new TAnyInt(10));

Drugi wariant.
Wprowadzasz do TAny składową z wartością którą zwraca typeid(typ) oraz ze wskaźnikiem typu void pod który w odpowiednim konstruktorze przydzielasz pamięć.
Destruktor musi sprawdzać tą składową z id. Metody SetInt, GetInt muszą sprawdzać czy id==typeid(int) itd

0

Zawsze możesz użyć wskaźników na void, ale wtedy sam musisz pamiętać jaki jest typ umieszczonych w nim elementów.

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