interfejs C++

0

Witam
Używam kompilator Visual C++ 2005. Nie chce mi się skompilować taki poniższy kod, wywołuje się unresolved external symbols i odwołanie do metody smart_ptr_interface::release()

template <typename T> class smart_ptr_interface
{
    public:
		smart_ptr_interface(T* pValue): pData(pValue){}
		virtual ~smart_ptr_interface()
		{
		    release();
		}

		T& operator* ()
		{
			return *pData;
		}

		T* operator-> ()
		{
			return pData;
		}

        protected:
		virtual void release() = 0;
		/*{ 
			delete pData; 
		}*/

	protected:
		T* pData;
};
template <typename T> class smart_rel_com_ptr: smart_ptr_interface<T>
{
    public:
		smart_rel_com_ptr(T* pValue): smart_ptr_interface<T>(pValue){}
		virtual ~smart_rel_com_ptr(){}

    protected:
		void release() 
		{
			pData->Release();
                        delete pData;
		}
};

Gdy natomiast zdefiniuję metodę smart_ptr_interface::release() to z kolei jak się wywołuje destruktor dla smart_ptr_interface to mi woła metodę smart_ptr_interface::release() zamiast smart_rel_com_ptr::release(). Moim zdaniem nie powinno być błędu z "unresolved..." to raz a dwa jak już zdefiniuję sobie metodę to jako że ona jest wirtualna to powinna być wywoływana ta z klasy pochodnej. Wiem jak te błędy obejś ale dziwię się że to mi nie działa w ten sposób.

0

Jakby ta funkcjonalność działała (nie było tych błędów) to byłoby prościej bo można by zdefiniować flow kodu na poziomie interfejsu a potem w klasach pochodnych definiujemy sobie tylko metody a główny algorytm (flow kodu) już mamy w klasie bazowej. A tu zonk bo wywołują się metody z klasy bazowej.

1

Przecież w klasie smart_ptr_interface nie ma definicji tej metody. Skąd linker ma ją wziąć? release(); w destruktorze zawsze wywoła metodę z tej klasy, nie będzie wirtualnego wywołania.

Cokolwiek robisz, w bibliotece standardowej C++ są już smart pointery.

0

Oto przykład jak mój kod wygląda przez brak takiej funkcjonalności. Muszę w każdej klasie pochodnej zdefiniować destruktor i tam wywoływac metode release().

template <typename T> class smart_ptr_interface
{
    public:
		smart_ptr_interface(T* pValue): pData(pValue){}
		virtual ~smart_ptr_interface(){}

		T& operator* ()
		{
			return *pData;
		}

		T* operator-> ()
		{
			return pData;
		}

    protected:
		virtual void release() = 0;

	protected:
		T* pData;
};

template <typename T> class smart_ptr: smart_ptr_interface<T>
{
    public:
		smart_ptr(T* pValue): smart_ptr_interface<T>(pValue){}
		virtual ~smart_ptr()
		{
		    release();
		}

    protected:
		void release()
		{
            delete pData;
		}
};

template <typename T> class smart_com_ptr: smart_ptr_interface<T>
{
    public:
		smart_com_ptr(T* pValue): smart_ptr_interface<T>(pValue){}
		virtual ~smart_com_ptr()
		{
		    release();
		}

	protected:
		void release() 
		{
			pData->Release();
		}
};

template <typename T> class smart_rel_com_ptr: smart_ptr_interface<T>
{
    public:
		smart_rel_com_ptr(T* pValue): smart_ptr_interface<T>(pValue){}
		virtual ~smart_rel_com_ptr()
		{
		    release();
		}

    protected:
		void release() 
		{
			pData->Release();
                       delete pData;
		}
};
0

ok rozumiem czyli w destruktorze klasy bazowej nie da rady nic wywołać z metod wirtualnych z klas pochodnych. Czyli destruktor jest wyjątkiem, jakby to była każda inna metoda to by było wywołanie z klasy pochodnej.

1

Kiedy wykonywany jest konstruktor i destruktor wirtualne wywołania nie działają. Tak skonstruowany jest język i nic z tym nie zrobisz. Wynika to z kolejności wywołań: w przypadku destruktorów najpierw wywoływany jest destruktor klasy pochodnej a dopiero potem destruktor klasy bazowej. W destruktorze klasy bazowej nie ma już sensu wykonywać wirtualnych wywołań no bo klasa pochodna już jest "zniszczona".

Zarówno w konstruktorach jak i destruktorach nie należy wywoływać funkcji wirtualnych. W najlepszym przypadku stanie się nie to, co miało, w najgorszym będzie undefined behavior. Poczytaj np. tutaj: http://www.artima.com/cppsource/nevercall.html

W C++ już są smart pointery i prawdopodobnie nie musisz pisać swoich.

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