Шаблон наблюдателя в C ++ - PullRequest
0 голосов
/ 22 января 2011

У меня небольшие проблемы с шаблоном наблюдателя. У меня есть класс напитков, в котором отлично используется декоратор.Я пытаюсь внедрить наблюдателя, чтобы в этом случае наблюдатель (скажем, мобильный телефон / текстовое сообщение) узнал, когда будет выполнен заказ.я не буду включать классы напитков / декораторов, так как они работают нормально.

В основном я собирался сделать что-то вроде этого:

Subject mySubject = new Subject();
Observer myObserver1 = new Observer1();
Observer myObserver2 = new Observer2();

// register observers
mySubject.Register(myObserver1);
mySubject.Register(myObserver2);

mySubject.Notify("message 1");
mySubject.Notify("message 2");

У меня есть предметный класс, наблюдатель, класс поведения телефонаи класс cellphone1, cellphone2 ..

Вот класс объекта

#ifndef _SUBJECT_
#define _SUBJECT_

//#include "Starbuzz.h"
//#include "Starbuzz2.h"
#include "Observer.h"
#include <list>

namespace CoffeeHouse {
namespace Observers {


class Subject  {


private:
std::list< Observer* > observers;

public:
Subject();
~Subject();

void Subject::Register(Observer observer)
{

//if (!observers.(observer))
//{

observers.insert(observer);
}
//}

//void Unregister(Observer observer)
//{
// if observer is in the list, remove
//if (observers.Contains(observer))
//{
//observers.Remove(observer);
//}
//}

void Notify(std::string message)
{
//need loop
Observer observer;
observer.update(message);


}
//}
//}

//void Subject::registerObserver( Observer* o ) { assert( o );
    //_observers.push_front(o);
//}
//void Subject::removeObserver( Observer* o ) { assert( o );
//  _observers.remove(o);
//}
//void Subject::notifyObservers() const {
    //for( std::list< Observer* >::iterator iterator = _observers.begin();   _observers.end() != iterator; ++iterator ) {
        //Observer* observer = *iterator;
        //observer->update(message);
    //}
//}
};
} // namespace Observer
} 


#endif

Вот класс наблюдателя

#ifndef _OBSERVER_
#define _OBSERVER_

#include <string>

namespace CoffeeHouse {
namespace Observers {

class Subject;

class Observer {

//public: virtual ~Observer() = 0; 

public: virtual void Update(std::string message) = 0;
};

Вот класс поведения телефона

#ifndef _PHONEBEHAVIOR_
#define _PHONEBEHAVIOR_

namespace CoffeeHouse {
namespace Observer {

class PhoneBehavior {
public: virtual void Update() const = 0;
};
protected: virtual ~PhoneBehavior() = 0 {

};


};

} // namespace Observer
} //

вот мобильный телефон 1

#ifndef _CELLPHONE1_
#define _CELLPHONE1_

namespace CoffeeHouse {
namespace Observer {
include<iostream>
class CellPhone1: public Observer, public PhoneBehavior {
public: 
    CellPhone1();
    ~CellPhone1();
virtual void Update(std::string message)
 {
   std::cout << "CellPhone1: " << message;
}
};

} // namespace Observer
} //

#endif

вот ошибки, которые я получаю ..

error C2259: 'CoffeeHouse::Observers::Observer' : cannot instantiate abstract class
1>        due to following members:
1>        'void CoffeeHouse::Observers::Observer::update(std::string)' : is abstract
see declaration of 'CoffeeHouse::Observers::Observer::update'
error C2661: 'std::list<_Ty>::insert' : no overloaded function takes 1 arguments
with[_Ty=CoffeeHouse::Observers::Observer *

error C2259: 'CoffeeHouse::Observers::Observer' : cannot instantiate abstract class
due to following members:
'void CoffeeHouse::Observers::Observer::update(std::string)' : is abstract
observer.h(15) : see declaration of 'CoffeeHouse::Observers::Observer::update

Когда я нажимаю на ошибку "не могу создать экземпляр абстрактного класса"приводит меня к:

void Subject::Register(Observer observer)

Я понимаю, что абстрактные классы созданы таким образом, что их нельзя создать!

Как я могу сделать обновление тогда ??какие-либо предложения лучшего способа?

Я ценю любую помощь!

Ответы [ 3 ]

1 голос
/ 22 января 2011

Одна ошибка состоит в том, что Subject :: Register в настоящее время получает объект Observer вместо указателя на Observer. Это означает, что вы пытаетесь создать экземпляр абстрактного объекта, что недопустимо.

1 голос
/ 22 января 2011

Проблемы, которые я вижу:

  • Вы используете пространство имен и класс называется Observer в PhoneBehavior и исходные файлы класса CellPhone1.
  • В исходном файле класса CellPhone1 вы не #include <string> или не используйте Пространство имен std для строки в void Update(string message)
  • В исходном файле класса PhoneBehavior virtual void update() должен иметь вероятно, есть заглавная "U", чтобы остаться в соответствии с вашим стилем кодирования и потому что это так называется в Исходный файл класса CellPhone1.
  • В исходном файле класса CellPhone1 у вас есть Cout <<"CellPhone1:" + message);. Это должно быть std::cout << "CellPhone1: " << message;
  • В исходном файле класса CellPhone1 вам нужно #include <iostream>
  • В исходном файле класса PhoneBehavior слишком много закрывающих скобок. И только закрывающая скобка, соответствующая открывающей скобке вашего class PhoneBehavior, должна иметь точку с запятой после нее.

Редактировать: Когда я говорю «исходный файл класса», я предполагаю, что ваш проект настроен с файлами CellPhone1.cpp, PhoneBehavior.cpp в зависимости от того, как вы задали свой вопрос.

0 голосов
/ 10 января 2019

С этим можно сделать все, что можно наблюдать:

https://simmesimme.github.io/tutorials/2015/09/20/signal-slot

#ifndef SIGNAL_H
#define SIGNAL_H

#include <functional>
#include <map>

//! A signal object may call multiple slots with the same
//! signature. You can connect functions to the signal which will be
//! called when the emit() method on the signal object is invoked. Any
//! argument passed to emit() will be passed to the given functions.
template <typename... Args>
class signal
{
public:
  //! Default constructor.
  signal(): m_slots(), m_current_id(0) {}

  //! Copy constructor. (deleted)
  signal(signal const& other) = delete;

  //! Assignment operator. (deleted)
  signal& operator=(signal const& other) = delete;

  //! Connects a member function to this signal.
  //!
  //! @code{.cpp}
  //! signal<> s;
  //! int id = s.connect_member(&myclass, MyClass::method);
  //! @endcode
  //!
  //! @param[in] instance Pointer to the instance to connect.
  //! @param[in] func Pointer to the member func to connect.
  //! @return id of object connected, to be used to disconnect.
  template <typename T>
  int connect_member(T *inst, void (T::*func)(Args...))
  {
    return connect([=](Args... args) {(inst->*func)(args...);});
  }

  //! Connects a const member function to this signal.
  //!
  //! @code{.cpp}
  //! signal<> s;
  //! int id = s.connect_member(&myclass, MyClass::method);
  //! @endcode
  //!
  //! @param[in] instance Pointer to the instance to connect.
  //! @param[in] func Pointer to the member func to connect.
  //! @return id of object connected, to be used to disconnect.
  template <typename T>
  int connect_member(T *inst, void (T::*func)(Args...) const)
  {
    return connect([=](Args... args) { (inst->*func)(args...);});
  }

  //! Connects a std::function function wrapper to this signal.
  //!
  //! This method can be used to adapt many kinds of callable objects
  //! to a signal.
  //!
  //! @code{.cpp}
  //! signal<> s;
  //! std::function<void()> f = std::bind(&signal_utest::test0, this);
  //! int id = s.connect(f);
  //! @endcode
  //!
  //! @param[in] slot Function object invoked on emit().
  //! @return id of object connected, to be used to disconnect.
  int connect(std::function<void(Args...)> const& slot) const
  {
    m_slots.insert(std::make_pair(++m_current_id, slot));
    return m_current_id;
  }

  //! Disconnects a previously connected function.
  //!
  //! @param[in] id Id returned by connect function.
  void disconnect(int id) const
  {
    m_slots.erase(id);
  }

  // Disconnects all previously connected functions.
  void disconnect_all() const
  {
    m_slots.clear();
  }

  //! Calls all connected functions.
  void emit(Args... p)
  {
    for (auto it : m_slots)
      it.second(p...);
  }

private:
  mutable std::map<int, std::function<void(Args...)>> m_slots;
  mutable int m_current_id;
};

#endif /* SIGNAL_H */

с тестами:

  signal<> s0;
  int id0 = -1;
  UTEST_CHECK(id0 != 1);
  id0 = s0.connect_member(this, &signal_utest::test0);
  UTEST_CHECK(id0 == 1);
  UTEST_CHECK(get_test0() == 0);
  s0.emit();
  UTEST_CHECK(get_test0() == 1);

  signal<int> s1;
  UTEST_CHECK(s1.connect_member(this, &signal_utest::test1) == 1);
  UTEST_CHECK(test1() == 0);
  s1.emit(1);
  UTEST_CHECK(test1() == 1);

  signal<int, int> s2;
  UTEST_CHECK(s2.connect_member(this, &signal_utest::test2) == 1);
  UTEST_CHECK(test2() == 0);
  s2.emit(1, 1);
  UTEST_CHECK(test2() == 2);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...