template<typename T>class Observer...template<typename T>Observer<T>::Observer(void)
-
Hi,
ich habe vor das MVC anzuwenden. Nach Lektüre des Buches "Design Patterns" und dem darin vorgeschlagenen MVC Entwurfsmuster habe ich im Internet eine "bessere" Lösung gefunden. In dieser Lösung wird das Problem mit Templates gelöst. Daruch entfallen "Casts" und das im Buch "Design Patterns" aufgezeigte Zeiger-Problem.
Also habe ich mal Testweise Code im Visual Studio 2008 kompiliert.#include "stdafx.h" #include <iostream> #include <vector> template <class T> class Observer { public: Observer() {} virtual ~Observer() {} virtual void update(T *subject)= 0; }; template <class T> class Subject { public: Subject() {} virtual ~Subject() {} void attach (Observer<T> &observer) { m_observers.push_back(&observer); } void notify () { std::vector<Observer<T> *>::iterator it; for (it=m_observers.begin();it!=m_observers.end();it++) (*it)->update(static_cast<T *>(this)); } private: std::vector<Observer<T> *> m_observers; }; class Temperature : public Subject<Temperature> { public: Temperature() {} ~Temperature() {} void temperatureChanged () {notify();} void getTemperature() {std::cout <<" Getting the temperature." << std::endl;} }; class Pressure : public Subject<Pressure> { public: Pressure() {} ~Pressure() {} void pressureChanged () {notify();} void getPressure() {std::cout << " Getting the pressure." << std::endl;} }; class EnvironmentWindow : public Observer<Temperature>, public Observer<Pressure> { public: EnvironmentWindow() {} ~EnvironmentWindow() {} void update (Temperature *subject) {std::cout << "Temperature was changed" << std::endl; subject->getTemperature();} void update (Pressure *subject) {std::cout << "Pressure was changed" << std::endl; subject->getPressure ();} }; class PanicSirene : public Observer<Temperature> { public: PanicSirene() {} ~PanicSirene() {} void update (Temperature *subject) { std::cout << "Temperature was changed, sound the sirene" << std::endl; subject->getTemperature(); } }; int _tmain(int argc, _TCHAR* argv[]) { Temperature temp; Pressure press; EnvironmentWindow win; PanicSirene panic; temp .attach (win ); temp .attach (panic); press.attach (win ); temp.temperatureChanged (); press.pressureChanged (); return (0); }Jo, funktioniert. Da ich aber gerne die Klassen in ".h" und ".cpp" nutze um Deklaration und Definition zu trennen abe ich folgendes gemacht:
Observer.h
#pragma once template<typename T>class Observer { public: Observer(void); virtual ~Observer(void); virtual void update( T* )= 0; };Observer.cpp
#include "Observer.h" template<typename T>Observer<T>::Observer(void) { } template<typename T>Observer<T>::~Observer(void) { }dann ändern:
#include "Observer.h" /* template <class T> class Observer { public: Observer() {} virtual ~Observer() {} virtual void update(T *subject)= 0; }; */bekomme ich Linkerfehler:
unresolved external symbol "public: virtual __thiscall Observer<class Temperature>::~Observer<class Temperature>(void)" (??1???0EnvironmentWindow@@QAE@XZ$0
unresolved external symbol "public: __thiscall Observer<class Pressure>::Observer<class Pressure>(void)" (??0?$Observer@VPressure@@@@QAE@XZ) referenced in function "public: __thiscall EnvironmentWindow::EnvironmentWindow(void)" (??0EnvironmentWindow@@QAE@XZ)
unresolved external symbol "public: __thiscall Observer<class Temperature>::Observer<class Temperature>(void)" (??0?$Observer@VTemperature@@@@QAE@XZ) referenced in function "public: __thiscall EnvironmentWindow::EnvironmentWindow(void)" (??0EnvironmentWindow@@QAE@XZ)
unresolved external symbol "public: virtual __thiscall Observer<class Pressure>::~Observer<class Pressure>(void)" (??1?$Observer@VPressure@@@@UAE@XZ) referenced in function "public: virtual __thiscall EnvironmentWindow::~EnvironmentWindow(void)" (??1EnvironmentWindow@@UAE@XZ)
Der Compiler hat mit der Überstetzung kein Problem, der Linker aber schon. Er findet die Konstruktoren und die Destruktoren nicht.
Ich habe keinen Anstatz zur Lösung des Problems. Wieso ging das vorher als ich den Observer noch nicht in Header- und cpp-Datei ausgelagert habe?
-
Guck mal unter Punkt 5..
-
Ach schitepuupen...
Ok. So gehts

#include "Observer.h" template<typename T>Observer<T>::Observer(void) { } template<typename T>Observer<T>::~Observer(void) { } //Klassen bekannt machen... class Temperature; class Pressure; //Der "explicit" Instanziierungteil... template class Observer<Temperature>; template class Observer<Pressure>;Danke.