I have this mediator pattern:
File actor.hpp
#pragma once
#include <memory>
#include "mediator.hpp"
class actor : std::shared_from_this<actor>
{
public:
actor(std::shared_ptr<mediator> mediator) : mediator_(mediator)
{
}
virtual ~actor() = 0;
virtual void changed()
{
mediator_->actor_changed(std::make_shared<actor>(this));
}
private:
std::shared_ptr<mediator> mediator_;
};
File mediator.hpp
#pragma once
#include <memory>
class actor;
class mediator : public std::shared_from_this<mediator>
{
public:
virtual ~mediator() = 0;
virtual void actor_changed(std::shared_ptr<actor> actor) = 0;
}
An implementation of an actor request_handler.hpp
#pragma once
#include "actor.hpp"
class request_handler : public actor
{
public:
request_handler(std::shared_ptr<mediator> mediator) : actor(mediator)
{
}
void handle_request()
{
changed();
}
};
But I get the error message
actor.hpp:16 error: invalid new-expression of abstract class type 'actor'
because I cannot instatiate an abstract class. But what would be the correct way of doing this?
This code:
mediator_->actor_changed(std::make_shared<actor>(this));
is logically equal to:
auto ptr = std::shared_ptr<actor>( new actor( this ) );
mediator_->actor_changed(ptr);
and this is most probably not what you want, so you need to call shared_from_this() instead:
mediator_->actor_changed( this->shared_from_this() );
and class you need to inherit from is called std::enable_shared_from_this not shared_from_this
Related
I have an abstract class as follows:
class AbstractClass : public std::enable_shared_from_this<AbstractClass> {
public:
virtual ~AbstractClass() = default;
virtual bool Start() = 0;
virtual void Stop() = 0;
};
This is the derived class:
class DerivedClass : public AbstractClass {
public:
bool Start() override;
void Stop() override;
}
I am trying to create an object of derived class and a thread for the derived class method in another file:
// Create object
derivedClass_.reset(...);
//Start a thread for the derived class method
std::unique_ptr<boost::thread> derivedClassThread_;
derivedClassThread_.reset(new boost::thread(std::bind(&DerivedClass::Start,
derivedClass_)));
When I compile this, I get some weird errors:
error: no type named 'type' in 'class std::result_of<bool
(DerivedClass::* const&(const volatile
std::shared_ptr&))()>'
Could someone help me out?
Your code is not selfcontained, so we have to guess things. Here's what I think you would have/want:
Live On Coliru
#include <boost/thread.hpp>
#include <memory>
#include <iostream>
class AbstractClass : public std::enable_shared_from_this<AbstractClass> {
public:
virtual ~AbstractClass() = default;
virtual bool Start() = 0;
virtual void Stop() = 0;
};
class DerivedClass : public AbstractClass {
public:
bool Start() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
return true;
}
void Stop() override { }
};
int main()
{
// Create object
std::shared_ptr<AbstractClass> derivedClass_ =
std::make_shared<DerivedClass>();
// Start a thread for the derived class method
auto derivedClassThread_ = std::make_unique<boost::thread>(
[derivedClass_] { derivedClass_->Start(); });
if (derivedClassThread_ && derivedClassThread_->joinable())
derivedClassThread_->join();
derivedClassThread_ = std::make_unique<boost::thread>(
std::bind(&AbstractClass::Start, derivedClass_));
if (derivedClassThread_ && derivedClassThread_->joinable())
derivedClassThread_->join();
}
Which compiles without trouble.
Updated in response to the comment, showed that you can actually do it with std::bind just the same.
Prints:
virtual bool DerivedClass::Start()
virtual bool DerivedClass::Start()
Well, i have next code:
#include <type_traits>
#include <iostream>
#include <string>
#include <list>
#include <functional>
class base_main
{
public:
virtual ~base_main()
{
}
// some methods
};
class base_1 : virtual public base_main
{
// some methods
};
class base_2 : virtual public base_main
{
// some methods
};
class base_3 : virtual public base_main
{
// some methods
};
class object : public base_1, public base_2, public base_3
{
// some methods
};
// in other *hpp file
class object_controller_listener
{
public:
virtual void object_created( base_main* o )
{
// well, i want to work only with base_1 and base_2 interfaces, but not with base_3, and also i don't want to know something about object class in this *hpp
// is it good code design?
auto* xxx = dynamic_cast<base_1*>( o );
}
};
class objects_controller
{
void create()
{
std::unique_ptr<object> obj;
// ...
for( auto listener : m_listeners )
listener->object_created( obj.get() );
}
std::list<object_controller_listener*> m_listeners;
};
int main()
{
}
The question is - how can i work only with base_1 and base_2 interfaces? Should i create two separate listeners for them, and send two events in create() function, or should i use dynamic_cast for downcasting and send only one event in create() function? Is this good code design or is this feels like code smell?
UPD:
For example: base_1 - is render_base class, which contains render data, and have functions for set and get this data base_2 - collider base class which contains collider data, and have functions for set and get this data base_3 is physic base class and object is inheritance of all this classes. And when i want work only with render class i use create event which send only render_base class to the render_system, which works only with renders objects and truly use polymorphism. But if i want in some other place work with collider and physic objects, without knowledge about render - how can i use polymorphism here in base classes?
It is hard to tell what design you should choose as this heavily depends on the overall structure of the application.
Generally, I would avoid having a function with the signature virtual void object_created( base_main* o ) in which you dynamically cast to base_* and work on that directly in this function. Because the function signature is part of the documentation of the API.
So I would create distinct functions for base_1 and base_2 and call those.
How to do that depends again on the overall structure. You could create a helper function, that forwards the call to the other functions (this is just a fast implementation how that could look like:
template <typename DestT, typename SrcT, typename T>
void forward_if(SrcT obj, T *o, void (T::*f)(DestT)) noexcept {
if (auto tmp = dynamic_cast<DestT>(obj); tmp != nullptr) {
(o->*f)(tmp);
}
}
And then you could use it like this:
#include <iostream>
#include <vector>
class base_main {
public:
virtual ~base_main() {}
};
class base_1 : virtual public base_main {};
class base_2 : virtual public base_main {};
class base_3 : virtual public base_main {};
class object : public base_1, public base_2, public base_3 {};
template <typename DestT, typename SrcT, typename T>
void forward_if(SrcT obj, T *o, void (T::*f)(DestT)) noexcept {
if (auto tmp = dynamic_cast<DestT>(obj); tmp != nullptr) {
(o->*f)(tmp);
}
}
struct listener_base {
virtual void object_created(base_main *o) = 0;
};
struct specific_listener : public listener_base {
void object_created(base_main *o) override {
forward_if<base_1 *>(o, this, &specific_listener::object_created);
forward_if<base_2 *>(o, this, &specific_listener::object_created);
}
void object_created(base_1 *o) {
std::cout << "object created base_1" << std::endl;
}
void object_created(base_2 *o) {
std::cout << "object created base_2" << std::endl;
}
};
int main() {
std::vector<listener_base *> listeners;
listeners.push_back(new specific_listener());
object o;
for (auto listener : listeners) {
listener->object_created(&o);
}
return 0;
}
I want to create a List which is able to hold every Object I throw at it as long as they share the same ABSTRACT base class.
Here is an sample code of how I want to achieve this.
#include <iostream>
#include <memory>
#include <list>
class Observer
{
public:
virtual void update() = 0;
};
class RequestStateObserver
{
public:
void registerObserver(std::shared_ptr<Observer> o){
observerList.push_back(o);
}
private:
std::list<std::shared_ptr<Observer>> observerList;
};
class RestRequestCreator :Observer
{
void update() override;
};
void RestRequestCreator::update()
{
std::cout<<"RestRequestCreator::update()";
}
class dbHandler :Observer
{
void update() override;
};
void dbHandler::update() {
std::cout<<"dbHandler::update()";
}
int main()
{
RestRequestCreator rrc;
RequestStateObserver rso;
dbHandler dbhandler;
std::shared_ptr<RequestStateObserver> stateObserver;
std::shared_ptr<RestRequestCreator> rr_ptr = std::make_shared<RestRequestCreator>(rrc);
rso.registerObserver(rr_ptr);
rso.registerObserver(std::make_shared<Observer> (dbhandler));
}
o->registerObserver(std::make_shared<Observer> dbhandler)will tell me I can't create Observer since it's an abstract class which totally makes sense but
o->registerObserver(rr_ptr) will tell me it can't convert std::shared_ptr<Observer> to std::shared_ptr<RestRequestCreator>
I am at the moment not sure how to fix this problem or what exactly I should try next.
Would Templates help me? If I am correct they would just allow me to put as many objects of ONE child class into my List, if that's wrong please tell me and I will re-read about templates again.
The conversion fails because Observer is a private base of RestRequestCreator, and is inaccessible.
You'll need to use public inheritance for the compiler to implicitly convert from the derived class to the base:
class RestRequestCreator :public Observer
That fixes the immediate problem, but leaves the problems with make_shared<Observable> on the next line.
Also: should an observee co-own an observer? In general that would not be the case. Therefore, instead use regular pointers.
#include <list>
#include <iostream>
using std::cout;
class Observer
{
public:
virtual void update() = 0;
};
class ConcreteObserver : public Observer
{
public:
void update() override {
cout << "ConcreteObserver noticed update\n";}
};
class OtherKindConcreteObserver : public Observer
{
public:
void update() override {
cout << "OtherKindObserver noticed update\n";
}
};
class Subject
{
public:
void registerObserver( Observer* o) {
observerList.push_back( o);
}
void signalObservers() {
for ( auto observer : observerList)
observer->update();
}
private:
std::list<Observer*> observerList;
};
int main() {
ConcreteObserver observer1;
OtherKindConcreteObserver observer2;
Subject subject;
subject.registerObserver( &observer1);
subject.registerObserver( &observer2);
subject.signalObservers();
return 0;
}
Please help me to understand strange behavior:
I use dynamic_cast from MyObject to MyLogicObject when a destructor ~MyLogicObject() in processing, but compiler throw an exception: non_rtti_object.
I'm sure that object MyObject is a polymorph type. Where am I wrong?
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <string>
class A
{
int a;
};
class B
{
int b;
};
class MyObject: public A,
public B// if comment this row, and don't use multi inheritable, everything will be fine
{
private: std::string name;
private: bool singleshot;
public: MyObject(void);
public: virtual ~MyObject(void);
protected: void Destroying(void);
public: std::string GetName(void);
public: virtual bool Rename(std::string _newName);
};
#endif
#include "MyObject.h"
#include "MyLogicObject.h"
MyObject::MyObject(void): singleshot(true)
{}
MyObject::~MyObject(void)
{
printf("\n~my object\n");
Destroying();
}
void MyObject::Destroying(void)
{
if(singleshot)
{
printf("\nexception!\n");
dynamic_cast<MyLogicObject*>(this);// exception: non_rtti_object
singleshot = false;
}
}
std::string MyObject::GetName(void)
{
return name;
}
bool MyObject::Rename(std::string _newName)
{
name = _newName;
return true;
}
#ifndef MYLOGICOBJECT_H
#define MYLOGICOBJECT_H
#include "MyObject.h"
class MyLogicObject: public virtual MyObject // if not use virtual inheritance (instead, use the standard inheritance), everything will be fine
{
public: MyLogicObject(void);
public: virtual ~MyLogicObject(void);
public: virtual void Update(float _delta = 0.0f);
// if reimplement virtual method of base class, everything will be fine
/*
public: virtual bool Rename(std::string _newName)
{
return MyObject::Rename(_newName);
}
*/
};
#endif
#include "MyLogicObject.h"
MyLogicObject::MyLogicObject(void)
{}
MyLogicObject::~MyLogicObject(void)
{
printf("\n~my logic object\n");
Destroying();
}
void MyLogicObject::Update(float _delta)
{}
#include <conio.h>
#include <stdio.h>
#include "MyLogicScene.h"
class C
{
int c;
};
class DerivedObject: public MyLogicObject,
public C// if comment this row, and don't use multi inheritable, everything will be fine
{
public: DerivedObject(void)
{}
public: virtual ~DerivedObject(void)
{
printf("~derived object: %s\n", GetName().c_str());
//Destroying(); // if call Destroying in this place, overything will be file
}
};
int main()
{
DerivedObject* object1 = new DerivedObject();
object1->Rename("object1");
printf("delete object1...\n");
delete object1;
getch();
return 0;
}
You are trying to dynamic cast an object of a base class (MyObject) type to the derived class (MyLogicObject). And this conversion is not allowed with dynamic_cast unless the base class is polymorphic and rtti is enabled. See this for reference.
So you basically need to enable rtti in your compiler options.
Once that is done make sure that object1 is a complete object of the derived class (MyLogicObject) for the cast to work without raising an exception.
It would work in the opposite scenario too. If you were trying for example to dynamic cast an object of a derived class (MyLogicObject) type to the base class (MyObject).
I have a SuperParent class, a Parent class (derived from SuperParent) and both contain a shared_ptr to a Child class (which contains a weak_ptr to a SuperParent). Unfortunately, I'm getting a bad_weak_ptr exception when trying to set the Child's pointer. The code is the following:
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
using namespace boost;
class SuperParent;
class Child {
public:
void SetParent(shared_ptr<SuperParent> parent)
{
parent_ = parent;
}
private:
weak_ptr<SuperParent> parent_;
};
class SuperParent : public enable_shared_from_this<SuperParent> {
protected:
void InformChild(shared_ptr<Child> grandson)
{
grandson->SetParent(shared_from_this());
grandson_ = grandson;
}
private:
shared_ptr<Child> grandson_;
};
class Parent : public SuperParent, public enable_shared_from_this<Parent> {
public:
void Init()
{
child_ = make_shared<Child>();
InformChild(child_);
}
private:
shared_ptr<Child> child_;
};
int main()
{
shared_ptr<Parent> parent = make_shared<Parent>();
parent->Init();
return 0;
}
This is because your Parent class inherits enable_shared_from_this twice.
Instead, you should inherit it once - through the SuperParent. And if you want to be able to get shared_ptr< Parent > within Parent class, you can inherit also it from the following helper class:
template<class Derived>
class enable_shared_from_This
{
public:
typedef boost::shared_ptr<Derived> Ptr;
Ptr shared_from_This()
{
return boost::static_pointer_cast<Derived>(static_cast<Derived *>(this)->shared_from_this());
}
Ptr shared_from_This() const
{
return boost::static_pointer_cast<Derived>(static_cast<Derived *>(this)->shared_from_this());
}
};
Then,
class Parent : public SuperParent, public enable_shared_from_This<Parent>