I'm trying to practice "Observer Design Pattern". When I thought a abstract's pure virtual method has been override by it's derived class, a error occurred.
There is a observer which is an abstract class in a independent file:
#ifndef DESIGN_PATTERNS_OBSERVER_H
#define DESIGN_PATTERNS_OBSERVER_H
#include "subject.h"
class Subject;
class Observer{
protected:
Observer();
public:
virtual ~Observer();
virtual void update(Subject *the_changed_subject) = 0;
};
Observer::Observer() {}
Observer::~Observer() {}
#endif //DESIGN_PATTERNS_OBSERVER_H
Observer defined a pure virtual method "update" which overrides as follow:
#ifndef DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#define DESIGN_PATTERNS_CONCRETE_OBSERVER_H
#include <iostream>
#include "observer.h"
#include "concrete_subject.h"
class ConcreteObserver : public Observer{
public:
void update(Subject *the_changed_subject) override {
auto cs = dynamic_cast<ConcreteSubject *>(the_changed_subject);
std::cout << "status changed to " << cs->get_status() << std::endl;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_OBSERVER_H
And also there is a subject which is an abstract class too.The error "pure virtual method called" happened in "notify" method where I had marked.
From debug, it seems "notify" uses Observer's "update" rather than ConcreteObserver's.
However,in main function the _observers should stored pointers of ConcreteObservers which override "update".
#ifndef DESIGN_PATTERNS_SUBJECT_H
#define DESIGN_PATTERNS_SUBJECT_H
#include <list>
#include "observer.h"
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
#endif //DESIGN_PATTERNS_SUBJECT_H
And it has a derived class "ConcreteSubject":
#ifndef DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#define DESIGN_PATTERNS_CONCRETE_SUBJECT_H
#include "subject.h"
class ConcreteSubject : public Subject {
private:
int status;
public:
ConcreteSubject() {
status = 0;
}
void set_status(int s) {
this->status = s;
Subject::notify();
}
int get_status() {
return status;
}
};
#endif //DESIGN_PATTERNS_CONCRETE_SUBJECT_H
The main function:
#include <iostream>
#include <vector>
#include "singleton.h"
#include "observer/concrete_subject.h"
#include "observer/concrete_observer.h"
void test2() {
ConcreteSubject concreteSubject;
std::vector<ConcreteObserver> observers;
for (int i = 0; i < 5; ++i) {
ConcreteObserver observer = ConcreteObserver();
concreteSubject.attach(&observer);
observers.push_back(observer);
}
concreteSubject.set_status(2);
}
int main() {
test2();
return 0;
}
As I mentioned before, the _observers of ConcreteSubject's super class Subject should stored pointers of ConcreteObservers which override "update" already.
I don't understand why Observer's "update" still called.
Here is another strange thing.I make a small test has almost the same relationship of classes I showed.But no error occured.
class ABaseA{
public:
virtual void do_some() = 0;
};
class MidA : public ABaseA{
public:
void do_some() override {
cout << "real do some" << endl;
}
};
class ABaseB{
private:
list<ABaseA*> *bases;
public:
ABaseB() {
bases = new list<ABaseA*>();
}
virtual ~ABaseB() = default;
virtual void add(ABaseA* item) {
bases->push_back(item);
}
virtual void do_active() {
for(ABaseA *p : *bases) {
p->do_some();
}
}
};
class MidB : public ABaseB{
public:
MidB() = default;
void active() {
ABaseB::do_active();
}
};
void test3() {
MidA midA;
MidB midB;
midB.add(&midA);
midB.active();
}
The only difference is this code is in one file.
In the file of Subject.h you should be transfer below code to Subject.cpp:
Subject::Subject() {
_observers = new std::list<Observer*>;
}
Subject::~Subject() {
delete _observers;
}
void Subject::attach(Observer *o) {
_observers->push_back(o);
}
void Subject::detach(Observer *o) {
_observers->remove(o);
}
void Subject::notify() {
for (Observer* observer : *_observers) {
//here is where error comes out, found by debug
observer->update(this);
}
}
Also you should be add class Observer; in top of Subject.h
#include <list>
#include "Observer.h"
class Observer; //you should be add this line
class Subject {
private:
std::list<Observer*> *_observers;
protected:
Subject();
public:
virtual ~Subject();
virtual void attach(Observer*);
virtual void detach(Observer*);
virtual void notify();
};
Related
I am having a hard time trying to compile the following code using clang compiler. I am not sure if I am using enable_shared_from_this and shared_From_this() in the right way, or breaking rule inadvertently. Can someone point me out what is exactly causing problem.
#include <iostream>
#include <memory>
class IB {
public:
virtual void Calle() =0;
virtual void Show() = 0;
};
class IC {
public:
virtual void Calle() =0;
virtual void Print() =0;
};
class CB;
class CC;
class CA : public std::enable_shared_from_this<CA> {
private:
std::shared_ptr<IB> m_ib;
public:
CA()
: m_ib(std::make_shared<CB>(shared_from_this())) {
std::cout << "Created CA obj\n";
}
void Calle() {
if(m_ib) m_ib->Calle();
// Show();
}
void Show() {
std::cout << "Printing from here. CA\n";
}
};
class CB : public IB, public std::enable_shared_from_this<CA> {
private:
std::shared_ptr<IC> m_ic;
std::shared_ptr<CA> m_ca;
public:
CB() : CB(nullptr){}
CB(const std::shared_ptr<CA> a)
: m_ca(a)
, m_ic(std::make_shared<CC>(shared_from_this())) {
std::cout << "Created CB obj\n";
}
virtual void Calle() override;
virtual void Show() override;
};
void CB::Calle() {
if(m_ca) m_ca->Show();
if(m_ic) m_ic->Print();
Show();
}
void CB::Show() {
std::cout << "Printing from here. CB\n";
}
class CC : public IC, public std::enable_shared_from_this<CA> {
private:
std::shared_ptr<IB> m_ib;
public:
CC()
: CC(nullptr){}
CC(const std::shared_ptr<CB> b)
: m_ib(b){
std::cout << "Created CC obj\n";
}
virtual void Calle() override;
virtual void Print() override;
};
void CC::Calle() {
if(m_ib) m_ib->Show();
}
void CC::Print() {
std::cout << "Printing from here. CC\n";
}
int main() {
auto a = std::make_shared<CA>();
a->Calle();
return 0;
}
I can't seem to figure out how to write the includes of the Visitor Pattern with this simple example. No matter what I do I always end up with circular dependencies, but no other way makes sense.
Also I apologize for the different header guards (pragma vs. #ifndef), I was testing #pragma out and hadn't updated the files yet.
Client.cpp
#include "OneVisitor.h"
#include "DataStructure.h"
int main (int argc, char * argv [])
{
OneVisitor v;
DataStructure d;
}
DataStructure.h
#ifndef _DATA_STRUCTURE_H_
#define _DATA_STRUCTURE_H_
#include "ElementA.h"
class DataStructure {
public:
DataStructure (Visitor & v)
{
std::cout << "ACCEPTS";
a->accept(v);
};
private:
ElementA * a;
};
#endif
Element.h
#ifndef _ELEMENT_H_
#define _ELEMENT_H_
#include "Visitor.h"
#include <iostream>
class Element {
public:
virtual void accept (Visitor & v) = 0;
void talk ()
{
std::cout << "ELEMENT TALKING";
};
};
#endif
ElementA.h
#pragma once
#include "Element.h"
#include "Visitor.h"
class ElementA : public Element {
public:
virtual void accept (Visitor & v) override
{
v.Visit(*this);
};
void talk ()
{
std::cout << "ELEMENT A TALKING";
};
};
Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
#include "ElementA.h"
class Visitor {
public:
virtual void Visit (ElementA & a) = 0;
};
#endif
OneVisitor.h
#ifndef _ONE_VISITOR_H_
#define _ONE_VISITOR_H_
#include "Visitor.h"
class OneVisitor : public Visitor {
public:
virtual void Visit (ElementA & a) override
{
a.talk();
};
};
#endif
When I run this, I get the error "Visitor has not been declared" in Element.h, ElementA.h, ElementB.h. How can i get Visitor defined in these classes without causing circular dependencies?
A visitor is a very abstract concept, and it makes sense to template it in this case. Using templates allows us to get rid of circular dependencies, and simplify things considerably.
// Visitor.hpp
#pragma once
template<class T>
class Visitor {
public:
virtual void visit(T& item) = 0;
virtual ~Visitor() = default;
};
Now, if you want to have visitor for Element, you could just use Visitor<Element>:
// Element.hpp
#pragma once
#include "Visitor.hpp"
#include <iostream>
class Element
{
public:
virtual void accept(Visitor<Element>& v)
{
v.visit(*this);
}
virtual void talk() {
std::cout << "Element talking!\n";
}
virtual ~Element() = default;
};
Now that we have these things, we can also write a function to convert lambdas into visitors:
template<class T, class Func>
struct FunctionVisitor : public Visitor<T> {
Func func;
FunctionVisitor() = default;
FunctionVisitor(FunctionVisitor const&) = default;
FunctionVisitor(FunctionVisitor&&) = default;
FunctionVisitor(Func const& func)
: func(func)
{
}
void visit(T& item) override {
func(item);
}
};
template<class T, class Func>
FunctionVisitor<T, Func> makeVisitor(Func const& f) {
return FunctionVisitor<T, Func>(f);
}
Bringing it all together
This allows us to write nice code like this:
#include "Element.hpp"
#include "Visitor.hpp"
#include <vector>
class ElemA : public Element {
public:
void talk() override {
std::cout << "ElemA talking!\n";
}
};
class ElemB : public Element {
public:
void talk() override {
std::cout << "ElemB talking!\n";
}
};
class ElemC : public Element {
public:
void talk() override {
std::cout << "ElemC talking!\n";
}
};
void visitAll(std::vector<Element*>& elements, Visitor<Element>& visitor) {
for(auto e : elements) {
e.accept(visitor);
}
}
int main() {
std::vector<Element*> elements {
new ElemA(),
new ElemB(),
new ElemC()
};
auto talk = [](Element& e) { e.talk(); };
visitAll(elements, makeVisitor<Element>(talk));
}
By using a forward declaration of the class ElementA; in Visitor.h
#ifndef _VISITOR_H_
#define _VISITOR_H_
// Just use a forward declaration of the class ElementA;
// NOTE1: The include of ElementA.h is not needed anymore.
// NOTE2: The visitor.h doesn't need to know what is defined
// in ElementA, only your .cpp needs, this is how forward
// declaration works.
class ElementA;
class Visitor {
public:
virtual void Visit (ElementA & a) = 0;
};
#endif
if I have the following code:
class A
{
public:
virtual void Yo();
}
class B : public A
{
public:
virtual void Yo() override;
}
Is there a way to force B to implement method Yo in A? Like an interface or more specifically (in this case) an abstract?
My full code is here:
BaseObject.h
#pragma once
namespace Game
{
namespace Model
{
namespace Graphic
{
class BaseObject
{
public:
int Width;
int Height;
float X;
float Y;
float Z;
virtual void SetUp() = 0;
virtual void Reset() = 0;
};
}
}
}
Player.cpp
#include "pch.h"
#include "Abstract\BaseObject.h"
using namespace Game::Model::Graphic;
class Player : public BaseObject
{
public:
Player();
~Player();
//virtual void SetUp();
//virtual void Reset() override;
};
in A make Yo pure virtual
virtual void Yo() = 0;
a complete example
#include <iostream>
struct A
{
virtual void Yo() = 0;
};
struct B : A
{
virtual void Yo() { std::cout << "I'm B\n"; }
};
int main()
{
B b;
b.Yo();
return (0);
}
if B doesn't implement Yo this will not compile.
The override keyword it's not needed in this case.
You have to take pointer of the base class to implement virtual functions in C++. This seems quite obvious. But i think we have missed that. The most basic example is given below.
#include <iostream>
using namespace std;
class base {
public:
virtual void vfunc() {
cout << "This is base's vfunc().\n";
}
};
class derived1 : public base {
public:
void vfunc() {
cout << "This is derived1's vfunc().\n";
}
};
int main()
{
base *p, b;
derived1 d1;
// point to base
p = &b;
p->vfunc(); // access base's vfunc()
// point to derived1
p = &d1;
p->vfunc(); // access derived1's vfunc()
return 0;
}
I am new to Design Pattern, and I'm trying the first example of (Head First Design Patterns) but I'm trying to code it in C++. I can't compile my code! I don't know why. Here's my code.
#include <iostream>
using namespace std;
class QuackBehavior
{
public:
virtual void quack();
virtual ~QuackBehavior();
};
class Quack : public QuackBehavior
{
public:
void quack()
{
cout<<"Quacking"<<endl;
}
};
class MuteQuack : public QuackBehavior
{
public:
void quack()
{
cout<<"<<< Silence >>>"<<endl;
}
};
class Squeak : public QuackBehavior
{
public:
void quack()
{
cout<<"Squeak"<<endl;
}
};
class FlyBehavior
{
public:
virtual void fly();
virtual ~FlyBehavior();
};
class FlyWithWings : public FlyBehavior
{
public:
void fly()
{
cout<<"I'm flying"<<endl;
}
};
class FlyNoWay : public FlyBehavior
{
public:
void fly()
{
cout<<"I can't fly"<<endl;
}
};
class Duck
{
public:
FlyBehavior *flyBehavior;
QuackBehavior *quackBehavior;
void display();
void performFly()
{
flyBehavior->fly();
}
void performQuack()
{
quackBehavior->quack();
}
};
class MallardDuck : public Duck
{
public:
MallardDuck()
{
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
};
int main()
{
Duck *mallard = new MallardDuck;
cout<<"Test"<<endl;
mallard->performFly();
// mallard->performQuack();
return 0;
}
Thanks for your help.
You get a compile error because you have not provided default definitions for functions in class QuackBehavior and class FlyBehavior.
Either you could provide default implementation or make the functions pure virtual.
Make the below two changes and your code should compile fine.
class QuackBehavior
{
public:
virtual void quack(){}
virtual ~QuackBehavior(){}
};
class FlyBehavior
{
public:
virtual void fly(){}
virtual ~FlyBehavior(){}
};
OR
class FlyBehavior
{
public:
virtual void fly() = 0;
};
class QuackBehavior
{
public:
virtual void quack() = 0;
};
I've a problem with this pattern under c++ on VS 2008.
The same code has been tested in gcc (linux, mac and mingw for
widnows) and it works.
I copy/paste the code here:
class MyCommand {
public:
virtual void execute() = 0;
virtual ~MyCommand () {};
};
class MyOperation {
public:
virtual void DoIt() {}; //I also write it not inline
};
class MyOperationDerived : public MyOperation {
public:
virtual void DoIt() {}; //I also write it not inline
};
class MyUndoStackCommand : public MyCommand {
public:
typedef void(MyOperation::*Action)();
MyUndoStackCommand(MyOperation *rec, Action action);
/*virtual*/ void execute();
/*virtual*/ ~MyUndoStackCommand();
private:
MyOperation *myReceiver;
Action myAction ;
};
in cpp:
#include "MyUndoStackCommand.h"
#include "MyOperation.h"
MyUndoStackCommand::~MyUndoStackCommand() {
}
MyUndoStackCommand::MyUndoStackCommand(myOperation *rec, Action
action): myReceiver(rec), myAction(action) {
}
void MyUndoStackCommand::execute() {
((myReceiver)->*(myAction))();
}
use in main.cpp:
MyReceiver receiver;
MyUndoStackCommand usc(&receiver, &MyOperation::DoIt);
usc.execute();
when I debug under visual studio only if I set inside MyUndoStackCommand, directly
myAction = &MyOperation::DoIt , it works, otherwise not.
Any advice?
thank you very much,
dan
Edit: The following code compiles with g++ - changes by Neil Butterworth flagged as //NB.
class MyCommand {
public:
virtual void execute() = 0;
virtual ~MyCommand () {};
};
class MyOperation {
public:
virtual void DoIt() {}; //I also write it not inline
};
class MyOperationDerived : public MyOperation {
public:
virtual void DoIt() {}; //I also write it not inline
};
class MyUndoStackCommand : public MyCommand {
public:
typedef void(MyOperation::*Action)();
MyUndoStackCommand(MyOperation *rec, Action action);
/*virtual*/ void execute();
/*virtual*/ ~MyUndoStackCommand();
private:
MyOperation *myReceiver;
Action myAction ;
};
MyUndoStackCommand::~MyUndoStackCommand() {
}
MyUndoStackCommand::MyUndoStackCommand(MyOperation *rec, //NB
Action action)
: myReceiver(rec), myAction(action) {
}
void MyUndoStackCommand::execute() {
((myReceiver)->*(myAction))();
}
int main() {
MyOperation receiver; //NB
MyUndoStackCommand usc(&receiver, &MyOperation::DoIt);
usc.execute();
}
With Neils edit this works fine in Visual Studio 2008.
// command.h
#pragma once
#include <iostream> // added for printing
using namespace std; // added for printing
class MyCommand {
public:
virtual void execute() = 0;
virtual ~MyCommand () {};
};
class MyOperation {
public:
virtual void DoIt() {
cout << "myoperation::doit()" << endl;
}; //I also write it not inline
};
class MyOperationDerived : public MyOperation {
public:
virtual void DoIt() {
cout << "myoperationderived::doit()" << endl;
}; //I also write it not inline
};
class MyUndoStackCommand : public MyCommand {
public:
typedef void(MyOperation::*Action)();
MyUndoStackCommand(MyOperation *rec, Action action);
/*virtual*/ void execute();
/*virtual*/ ~MyUndoStackCommand();
private:
MyOperation *myReceiver;
Action myAction;
};
// command.cpp
#include "command.h"
MyUndoStackCommand::~MyUndoStackCommand() {
}
MyUndoStackCommand::MyUndoStackCommand(/*m*/ MyOperation *rec, Action
action): myReceiver(rec), myAction(action) {
}
void MyUndoStackCommand::execute() {
((myReceiver)->*(myAction))();
}
// main.cpp
#include "command.h"
int main(){
MyOperationDerived receiver;
MyUndoStackCommand usc(&receiver, &MyOperation::DoIt);
usc.execute();
}
Will print:
"myoperationderived::doit()"