shared_from_this - derived classes (yes, I googled)
Please examine the following: //----------------------------------------------------------------------------- void TcpListener::Listen() { TcpServerSideConnection::SmartPtr newConnection = TcpServerSideConnection::Create(ioService_); TcpBaseSocket::SmartPtr ptr = shared_from_this(); TcpListener::SmartPtr me = boost::dynamic_pointer_cast<TcpListener, TcpBaseSocket>(ptr); /// Asynchronously accept one connection request when it occurs acceptor_.async_accept(newConnection->GetSocket(), boost::bind(&TcpListener::OnConnectionAccepted, me, newConnection, boost::asio::placeholders::error)); } It throws an exception, unwinds my stack and destroys my object on the assignment of shared_from_this. I forced at least one shared pointer to be created, by making factory methods from base on up the class hierarchy. I read on google that you can only use shared_from_this on ONE class type in a class hierarchy. I did not understand the details of why. following a peer's advice, I enabled_shared_from_this on the base class and attempted to cast it in the derived class methods, getting the result that I did. I am trying to use a smart pointer here, following the example code for boost::asio::ip::tcp, assuming that I want to ensure the instance of 'ths' is alive between the time of the async call and the time it completes! I do not see a way to do this when using a class hierarchy. My base classes do similar async calls and try to handle it similarlly, so I cannot enable_shared_from_this only on the most derived. As there is no guarentee that only the most derived will be instantiated. I have more than 3 classes in the inheritance hierarchy, any of which could be instantiated. TcpBase - holds the socket and a smart pointer to the io_service TcpConnection - Adds Write and Read methods TcpClientConnection - Adds Connect method TcpServerConnection - Does not have connect, but can only be instantiated by a TcpListener - Accepts connections and creates TcpServerConnections Any of these, except the very base can be instantiated. How do I work around this problem?
<...>
I read on google that you can only use shared_from_this on ONE class type in a class hierarchy. I did not understand the details of why.
You probably mean that you should inherit enable_shared_from_this only once. But then you can use shared_from_this wherever you wish.
Igor R <boost.lists <at> gmail.com> writes:
<...>
I read on google that you can only use shared_from_this on ONE class type
in a
class hierarchy. I did not understand the details of why.
You probably mean that you should inherit enable_shared_from_this only once. But then you can use shared_from_this wherever you wish.
I inherited from enable_shared_from_this in my base class. When I called shared_from_this() in my derived class it throws an exception. When I go up the call stack I see that in the boost implementation weak_ptr is NULL and count is NULL. I ensured the derived class was instatiated as a shared_ptr by using a fatory method. I don't know what else to do.
I inherited from enable_shared_from_this in my base class. When I called shared_from_this() in my derived class it throws an exception. When I go up the call stack I see that in the boost implementation weak_ptr is NULL and count is NULL.
I ensured the derived class was instatiated as a shared_ptr by using a fatory method.
If you create shared_ptr, as you described, and then call shared_from_this(), it should not throw exceptions. If it does, can you provide a trivial reproducing sample?
Igor R <boost.lists <at> gmail.com> writes:
I inherited from enable_shared_from_this in my base class. When I called shared_from_this() in my derived class it throws an exception. When I go up the call stack I see that in the boost implementation weak_ptr
is
NULL and count is NULL.
I ensured the derived class was instatiated as a shared_ptr by using a fatory method.
If you create shared_ptr, as you described, and then call shared_from_this(), it should not throw exceptions. If it does, can you provide a trivial reproducing sample?
Well, I tried to get a trivial example and ended up having a working example. I suppose my problem is in the non-trivial part of my code :) Is this the correct way to do it? #include <iostream> #include <boost/enable_shared_from_this.hpp> #include <boost/shared_ptr.hpp> //-------------------------- class A : public boost::enable_shared_from_this<A> { public: /// typedef boost::shared_ptr<A> SmartPtr; /// static A::SmartPtr Create() { A::SmartPtr instance; // Check arguments if any // Create an instance of this class instance.reset(new A()); return instance; } virtual ~A() { } protected: A() { } }; //-------------------------- class B : public A { public: /// typedef boost::shared_ptr<B> SmartPtr; /// static B::SmartPtr Create() { B::SmartPtr instance; // Check arguments if any // Create an instance of this class instance.reset(new B()); return instance; } /// virtual ~B() { } /// B::SmartPtr Foo() { A::SmartPtr temp = shared_from_this(); B::SmartPtr me = boost::shared_dynamic_cast<B, A>(temp); return me; } /// void Bar() const { std::cout << "Success!" << std::endl; } protected: /// B() : A() { } }; //-------------------------- int main() { B::SmartPtr b1 = B::Create(); B::SmartPtr b2 = b1->Foo(); if( b1 != b2 ) { std::cout << "they aren't equal." << std::endl; return 1; } b2->Bar(); return 0; }
Well, I tried to get a trivial example and ended up having a working example. I suppose my problem is in the non-trivial part of my code :)
Is this the correct way to do it?
#include <iostream>
#include <boost/enable_shared_from_this.hpp> #include <boost/shared_ptr.hpp>
//-------------------------- class A : public boost::enable_shared_from_this<A> { public:
/// typedef boost::shared_ptr<A> SmartPtr;
/// static A::SmartPtr Create() { A::SmartPtr instance;
// Check arguments if any
// Create an instance of this class instance.reset(new A());
return instance; }
virtual ~A() { }
protected:
A() { }
};
//-------------------------- class B : public A { public:
/// typedef boost::shared_ptr<B> SmartPtr;
/// static B::SmartPtr Create() { B::SmartPtr instance;
// Check arguments if any
// Create an instance of this class instance.reset(new B());
return instance; }
/// virtual ~B() { }
/// B::SmartPtr Foo() { A::SmartPtr temp = shared_from_this(); B::SmartPtr me = boost::shared_dynamic_cast<B, A>(temp);
return me; }
/// void Bar() const { std::cout << "Success!" << std::endl; }
protected:
/// B() : A() { } };
//-------------------------- int main() { B::SmartPtr b1 = B::Create(); B::SmartPtr b2 = b1->Foo();
if( b1 != b2 ) { std::cout << "they aren't equal." << std::endl; return 1; }
b2->Bar();
return 0; }
Your example compiles and works well. (Actually, you don't need shared_dynamic_cast here, static_pointer_cast would be well enough.)
participants (2)
-
Christopher Pisz
-
Igor R