Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Smart Pointer Issue

Reply
Thread Tools

Smart Pointer Issue

 
 
kmakaron11@gmail.com
Guest
Posts: n/a
 
      02-12-2009
Hello, I have the following classes:
class ServiceBase
{
public:
ServiceBase() {}
~ServiceBase() {}
void Stop() {}

};

class ServiceDerivateublic ServiceBase
{
public:
ServiceDerivate() {}
~ServiceDerivate() {}

};

And I have linked smart pointer class which, does not destroy, but
calls Stop method on its destruction:

template <class X> class ServicePtr
{
public:
explicit ServicePtr(X* p = 0) throw()
: itsPtr(p) {itsPrev = itsNext = this;}
~ServicePtr()
{release();}
ServicePtr(const ServicePtr& r) throw()
{acquire(r);}

ServicePtr& operator=(const ServicePtr& r)
{
if (this != &r) {
release();
acquire(r);
}
return *this;
}

X& operator*() const throw() {return *itsPtr;}
X* operator->() const throw() {return itsPtr;}
X* get() const throw() {return itsPtr;}
bool unique() const throw() {return itsPrev ? itsPrev==this :
true;}

private:
X* itsPtr;
mutable const ServicePtr* itsPrev;
mutable const ServicePtr* itsNext;

void acquire(const ServicePtr& r) throw()
{ // insert this to the list
itsPtr = r.itsPtr;
itsNext = r.itsNext;
itsNext->itsPrev = this;
itsPrev = &r;
r.itsNext = this;
}

void release()
{ // erase this from the list, delete if unique
if (unique())
itsPtr->Stop();
else {
itsPrev->itsNext = itsNext;
itsNext->itsPrev = itsPrev;
itsPrev = itsNext = 0;
}
itsPtr = 0;
}

};

Since ServiceBase and ServiceDerivated have to be dynamic castable i
wish I could use a pool of ServiceBase classes, and upon request to
spawn new ServicePtr holding dynamic_cast to ServiceBase. Sipmle
example:

int main()
{
ServicePtr<ServiceBase> sbase;
ServicePtr<ServiceDerivate> sderivate;

sderivate=sbase;

return 0;

}

which, produces:
"no matching function for call to
'ServicePtr<ServiceDerivate>:perator=(ServicePtr <ServiceBase>&)'
note: candidates are: ServicePtr<X>& ServicePtr<X>:perator=(const
ServicePtr<X>&) [with X = ServiceDerivate]

Can anybody help with this. Probably I am missing something.
I tryied to overload:
ServicePtr& operator=(const ServicePtr<ServiceBase>& r)
but I did not compiled either.
 
Reply With Quote
 
 
 
 
anon
Guest
Posts: n/a
 
      02-12-2009
wrote:
> Hello, I have the following classes:
> class ServiceBase
> {
> public:
> ServiceBase() {}
> ~ServiceBase() {}


Since you want to delete derived objects through the pointer/reference
of the base class, this destructor has to be virtual

> void Stop() {}
>
> };
>
> class ServiceDerivateublic ServiceBase
> {
> public:
> ServiceDerivate() {}
> ~ServiceDerivate() {}
>
> };
>
> And I have linked smart pointer class which, does not destroy, but
> calls Stop method on its destruction:
>
> template <class X> class ServicePtr
> {
> public:
> explicit ServicePtr(X* p = 0) throw()
> : itsPtr(p) {itsPrev = itsNext = this;}
> ~ServicePtr()
> {release();}
> ServicePtr(const ServicePtr& r) throw()
> {acquire(r);}
>
> ServicePtr& operator=(const ServicePtr& r)
> {
> if (this != &r) {
> release();
> acquire(r);
> }
> return *this;
> }


ServicePtr& operator=( ServicePtr<ServiceBase>& r)
{
release();

ServicePtr cpyObj( dynamic_cast<X*> (r.get()));
r.release();
acquire(cpyObj);
cpyObj.release();

return *this;
}

This might do what you want, but it is a dirty hack. There are probably
better ways (which I couldn't think of right now )

>
> X& operator*() const throw() {return *itsPtr;}
> X* operator->() const throw() {return itsPtr;}
> X* get() const throw() {return itsPtr;}
> bool unique() const throw() {return itsPrev ? itsPrev==this :
> true;}
>
> private:
> X* itsPtr;
> mutable const ServicePtr* itsPrev;
> mutable const ServicePtr* itsNext;
>
> void acquire(const ServicePtr& r) throw()
> { // insert this to the list
> itsPtr = r.itsPtr;
> itsNext = r.itsNext;
> itsNext->itsPrev = this;
> itsPrev = &r;
> r.itsNext = this;
> }
>
> void release()
> { // erase this from the list, delete if unique
> if (unique())
> itsPtr->Stop();
> else {
> itsPrev->itsNext = itsNext;
> itsNext->itsPrev = itsPrev;
> itsPrev = itsNext = 0;
> }
> itsPtr = 0;
> }
>
> };
>
> Since ServiceBase and ServiceDerivated have to be dynamic castable i
> wish I could use a pool of ServiceBase classes, and upon request to
> spawn new ServicePtr holding dynamic_cast to ServiceBase. Sipmle
> example:
>
> int main()
> {
> ServicePtr<ServiceBase> sbase;
> ServicePtr<ServiceDerivate> sderivate;
>
> sderivate=sbase;
>
> return 0;
>
> }
>
> which, produces:
> "no matching function for call to
> 'ServicePtr<ServiceDerivate>:perator=(ServicePtr <ServiceBase>&)'
> note: candidates are: ServicePtr<X>& ServicePtr<X>:perator=(const
> ServicePtr<X>&) [with X = ServiceDerivate]
>
> Can anybody help with this. Probably I am missing something.
> I tryied to overload:
> ServicePtr& operator=(const ServicePtr<ServiceBase>& r)
> but I did not compiled either.


Off course, because ServicePtr<ServiceBase> and
ServicePtr<ServiceDerivate> are two independent types.
 
Reply With Quote
 
 
 
 
SG
Guest
Posts: n/a
 
      02-12-2009
On 12 Feb., 14:00, anon <sfdhrt...@ebay.de> wrote:
> kmakaro...@gmail.com wrote:
> > Hello, I have the following classes:
> > class ServiceBase
> > {
> > * * * * public:
> > * * * * * * * * ServiceBase() {}
> > * * * * * * * * ~ServiceBase() {}


[...]

> ServicePtr& operator=( ServicePtr<ServiceBase>& r)
> * * * * *{
> * * * * * * *release();
>
> * * * * * * *ServicePtr cpyObj( dynamic_cast<X*> (r.get()));
> * * * * * * *r.release();
> * * * * * * *acquire(cpyObj);
> * * * * * * *cpyObj.release();
>
> * * * * * * *return *this;
> * * * * *}


dynamic_castis not going to work on non-polymorphic types.

Cheers!
SG
 
Reply With Quote
 
kmakaron11@gmail.com
Guest
Posts: n/a
 
      02-12-2009
There would be virtual dtor, I forgot to write it, when composing the
example above.
 
Reply With Quote
 
anon
Guest
Posts: n/a
 
      02-12-2009
SG wrote:
> On 12 Feb., 14:00, anon <sfdhrt...@ebay.de> wrote:
>> kmakaro...@gmail.com wrote:
>>> Hello, I have the following classes:
>>> class ServiceBase
>>> {
>>> public:
>>> ServiceBase() {}
>>> ~ServiceBase() {}

>
> [...]
>
>> ServicePtr& operator=( ServicePtr<ServiceBase>& r)
>> {
>> release();
>>
>> ServicePtr cpyObj( dynamic_cast<X*> (r.get()));
>> r.release();
>> acquire(cpyObj);
>> cpyObj.release();
>>
>> return *this;
>> }

>
> dynamic_castis not going to work on non-polymorphic types.


In this specific example it will work, but as I said it is a hack.
 
Reply With Quote
 
kmakaron11@gmail.com
Guest
Posts: n/a
 
      02-12-2009
I will test it tommorrow and will provide some feedback on final
ServicePtr class. Thank you anon
 
Reply With Quote
 
anon
Guest
Posts: n/a
 
      02-13-2009
SG wrote:
> On 12 Feb., 14:00, anon <sfdhrt...@ebay.de> wrote:
>> kmakaro...@gmail.com wrote:
>>> Hello, I have the following classes:
>>> class ServiceBase
>>> {
>>> public:
>>> ServiceBase() {}
>>> ~ServiceBase() {}

>
> [...]
>
>> ServicePtr& operator=( ServicePtr<ServiceBase>& r)
>> {
>> release();
>>
>> ServicePtr cpyObj( dynamic_cast<X*> (r.get()));
>> r.release();
>> acquire(cpyObj);
>> cpyObj.release();
>>
>> return *this;
>> }

>
> dynamic_castis not going to work on non-polymorphic types.
>
> Cheers!
> SG


This solves the problem. Anyone trying something stupid with the
template will notice :

ServicePtr& operator=( ServicePtr<ServiceBase>& r)
{
release();

X *tmp = dynamic_cast<X*> (r.get());
assert( NULL != tmp );

ServicePtr cpyObj( tmp );
r.release();
acquire(cpyObj);
cpyObj.release();

return *this;
}
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      02-13-2009
On Feb 12, 1:37 pm, kmakaro...@gmail.com wrote:
> Hello, I have the following classes:
> class ServiceBase
> {
> public:
> ServiceBase() {}
> ~ServiceBase() {}
> void Stop() {}
> };
>
> class ServiceDerivateublic ServiceBase
> {
> public:
> ServiceDerivate() {}
> ~ServiceDerivate() {}
> };


> And I have linked smart pointer class which, does not destroy,
> but calls Stop method on its destruction:


> template <class X> class ServicePtr
> {

[...]
> };


> Since ServiceBase and ServiceDerivated have to be dynamic
> castable i wish I could use a pool of ServiceBase classes, and
> upon request to spawn new ServicePtr holding dynamic_cast to
> ServiceBase.


I'm not sure I understand. In your example, there are no
virtual functions, so the classes aren't polymorphic. I
presume, however, that this is just an oversight in the example.
And of course, you don't need dynamic_cast to convert from
ServiceDerivate to ServiceBase; that's an implicit conversion.

> Sipmle example:


> int main()
> {
> ServicePtr<ServiceBase> sbase;
> ServicePtr<ServiceDerivate> sderivate;


> sderivate=sbase;


> return 0;
> }


> which, produces:
> "no matching function for call to
> 'ServicePtr<ServiceDerivate>:perator=(ServicePtr <ServiceBase>&)'
> note: candidates are: ServicePtr<X>& ServicePtr<X>:perator=(const
> ServicePtr<X>&) [with X = ServiceDerivate]


It also doesn't make sense unless sbase actually points to a
ServiceDerivate. If you want to support this, with dynamic
checking, you can add something like the following to your
ServicePtr:

template< typename T >
ServicePtr& operator=( ServicePtr< T > const& other )
{
X* tmp = dynamic_cast< X* >( other.get() ) ;
// rest of processing, however...
}

In this case, I'd probably derive ServicePtr from a non-template
ServicePtrBase which contained and handled the links.
Otherwise, you'll have to make all instances of the template
friends of the other instances. (As it stands,
ServicePtr< ServiceBase > cannot access any of the members of a
ServicePtr< ServiceDerivate >.)

> Can anybody help with this. Probably I am missing something.
> I tryied to overload:
> ServicePtr& operator=(const ServicePtr<ServiceBase>& r)
> but I did not compiled either.


What was the error message? And what did the code look like?

As mentionned above, you're likely to have problems with
accessing private data members; each instantiation of the
template is a separate, unrelated class. Moving the list
handling down to a common, non-template base class should solve
that. (It also has the advantage that you can get it out of the
header files, reducing their size.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Thomas J. Gritzan
Guest
Posts: n/a
 
      02-13-2009
anon schrieb:
> SG wrote:
>> On 12 Feb., 14:00, anon <sfdhrt...@ebay.de> wrote:
>>> kmakaro...@gmail.com wrote:
>>>> Hello, I have the following classes:
>>>> class ServiceBase
>>>> {
>>>> public:
>>>> ServiceBase() {}
>>>> ~ServiceBase() {}

>>
>> [...]
>>
>>> ServicePtr& operator=( ServicePtr<ServiceBase>& r)
>>> {
>>> release();
>>>
>>> ServicePtr cpyObj( dynamic_cast<X*> (r.get()));
>>> r.release();
>>> acquire(cpyObj);
>>> cpyObj.release();
>>>
>>> return *this;
>>> }

>>
>> dynamic_castis not going to work on non-polymorphic types.
>>
>> Cheers!
>> SG

>
> This solves the problem. Anyone trying something stupid with the
> template will notice :


Doesn't work.

> ServicePtr& operator=( ServicePtr<ServiceBase>& r)
> {
> release();
>
> X *tmp = dynamic_cast<X*> (r.get());
> assert( NULL != tmp );
>
> ServicePtr cpyObj( tmp );


This will make a smart pointer which owns the tmp pointer.

> r.release();


This lets r release its pointee, after that either its pointee is
deleted, or there's another smart pointer holding ownership.

> acquire(cpyObj);
> cpyObj.release();
>
> return *this;
> }


Here the class either stores an already deleted pointer, or there are
two families of smart pointers who owns the pointee.

Altough this smart pointer doesn't delete the pointee but call its
Stop() function, I don't think it's a good idea to call Stop() while
still using it.

--
Thomas
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Never ever use a raw pointer when a smart pointer can do the same job Hicham Mouline C++ 100 08-25-2009 05:07 PM
Smart Pointer release() const : it can set the pointer to null with the keyword "const"? coala C++ 1 09-06-2006 03:00 PM
Smart Pointer release() const : it can set the pointer to null with the keyword "const"? coala C++ 3 09-06-2006 02:58 PM
Smart Card Certificate Logon and Smart Card Wireless EAP-TLS erha Wireless Networking 0 05-19-2005 01:40 AM
trade 64mb smart media for 16mb smart media cards wjva Digital Photography 1 08-20-2003 08:30 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57