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>
Related
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;
}
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
I have a templated Base class that has multiple child classes and provides an abstract execute method. The children implement this method in different manners and may delegate execute calls to objects in the tail vector of the Base class.
In order to chain objects to the tail, the Base class provides some methods (createChild1, createChild2). Here is the code:
base.h
#pragma once
#include <memory>
#include <vector>
template<typename T>
class Child1;
template<typename T>
class Child2;
template<typename T>
class Base {
public:
std::vector<std::unique_ptr<Base<T>>> tail;
virtual void execute(const T &t) = 0;
Base<T> &createChild1() {
auto child = std::make_unique<Child1<T>>();
tail.push_back(std::move(child));
return *tail.back().get();
}
Base<T> &createChild2() {
auto child = std::make_unique<Child2<T>>();
tail.push_back(std::move(child));
return *tail.back().get();
}
};
child1.h
#pragma once
#include "base.h"
template<typename T>
class Child1 : public Base<T> {
public:
virtual void execute(const T &t) {
// do something with t
}
};
child2.h
#pragma once
#include "base.h"
template<typename T>
class Child2 : public Base<T> {
public:
virtual void execute(const T &t) {
// do something with t
// then delegate to t
for (auto &next : tail) {
next->execute(t);
}
}
};
main.cpp
#include <iostream>
#include "child1.h"
using namespace std;
int main(int argc, char **argv) {
Child1<int> c;
c.createChild2().createChild1();
c.execute(10);
return 0;
}
If I try to compile, I get a "implicit instantiation of undefined template 'Child2'" because in Base, the template class Child2 is only forward declared and its body is not known at that moment. Forward declaring Base in front of Child1 and Child2 and including the definitions of Child1 and Child2 in Base does not solve the problem, because then Child2 cannot access tail.
How can I solve this circular dependency? The code in Child1, Child2 and Base can change, but I want to keep the possibility to chain the create calls in main (therefore the create methods must be declared in the Base class).
The solution was prefixing the access to tail with this->. Therefore just child2.h must be changed:
#pragma once
#include "base.h"
template<typename T>
class Child2 : public Base<T> {
public:
virtual void execute(const T &t) {
// do something with t
// then delegate to t
for (auto &next : this->tail) {
next->execute(t);
}
}
};
Basically I have a class let's say Parameter that has a get and set variable.
I also have a base class let's say Vehicle that has a method registerParameter(...) that takes a pointer to function member as getter and a pointer to function member as setter. This method is then supposed to write those two pointers into an object of the parameter class and throws this object into a vector.
And last but not least we have a derived class let's say Car and we call registerParameter(...) with the string "color" as parameter name and a getter and setter from this derived class.
Example in code:
Parameter file
#ifndef BASE_H
#define BASE_H
#include "base.h"
class Parameter
{
std::string (Base::*get)();
void (Base::*set)(std::string);
};
#endif
Base file
#ifndef PARAMETER_H
#define PARAMETER_H
#include <vector>
#include "parameter.h"
class Base
{
public:
std::vector<Parameter> list;
void registerNew(std::string (Base::*get)(), void (Base::*set)(std::string))
{
Parameters parameter;
parameter.get = get;
parameter.set = set;
list.push_back(parameter);
}
};
#endif
Derived file
class Derived
{
public:
Derived derived()
{
registerNew(&getColor, &setColor);
}
std::string getColor()
{
return this->color;
}
std::string setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
I've been thinking about this for days now and I really need the solution until friday evening.
You cannot do what are trying:
The types std::string (Base::*)() and std::string (Derived::*)() are very different. std::string (Derived::*)() cannot be auto converted to std::string (Base::*)().
Take the following scenario.
struct Base
{
int foo() { return 10; }
};
struct Derived : Base
{
int bar() { return 20; }
};
int main()
{
Base base;
int (Base::*bf)() = &Base::foo;
(base.*bf)(); // Should be able to call Base:foo(). No problem.
bf = &Derived::bar; // This is a compiler error. However, if this were allowed....
(base.*bf)(); // Call Derived::bar()?? That will be a problem. base is not an
// instance of Derived.
}
Update
You can do something like:
#include <string>
#include <vector>
class Base;
// Create a base class Functor that provides the interface to be used by
// Base.
struct Functor
{
virtual ~Functor() {}
virtual std::string get(Base& base) = 0;
virtual void set(Base& base, std::string) = 0;
};
// Create a class template that implements the Functor interface.
template <typename Derived> struct FunctorTemplate : public Functor
{
// typedefs for get and set functions to be used by this class.
typedef std::string (Derived::*GetFunction)();
typedef void (Derived::*SetFunction)(std::string);
// The constructor that uses the get and set functions of the derived
// class to do itw work.
FunctorTemplate(GetFunction get, SetFunction set) : get_(get), set_(set) {}
virtual ~FunctorTemplate() {}
// Implement the get() function.
virtual std::string get(Base& base)
{
return (reinterpret_cast<Derived&>(base).*get_)();
}
// Implement the set() function.
virtual void set(Base& base, std::string s)
{
(reinterpret_cast<Derived&>(base).*set_)(s);
}
GetFunction get_;
SetFunction set_;
};
class Base
{
public:
std::vector<Functor*> functorList;
void registerFunctor(Functor* functor)
{
functorList.push_back(functor);
}
};
class Derived : public Base
{
public:
Derived()
{
// Register a FunctorTemplate.
registerFunctor(new FunctorTemplate<Derived>(&Derived::getColor,
&Derived::setColor));
}
std::string getColor()
{
return this->color;
}
void setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
Your base class should know the derived class. That sounds complex but the problem has been solved already:
template<typename DERIVED> class Base
{
public:
class Parameter {
std::string (DERIVED::*get)();
void (DERIVED::*set)();
};
private:
std::list<Parameter> list;
// ...
};
class Derived : public Base<Derived> // !!!
{
registerNew(&Derived::getColor, &Derived::setColor);
};
This solution is known as the Curiously Recurring Template Pattern (CRTP).