By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,864 Members | 1,727 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,864 IT Pros & Developers. It's quick & easy.

Casting class1<class2> to class1<class3 >

P: n/a
I'm using a library where the supplier has provided base class 'foo',
and a reference counting class which wraps 'foo':

------------------- library code -----------------------
template<class T>
refcount {
... // reference counting wrapper; like shared_ptr
};

class foo {
...
};

typedef refcount<foo> fooref;
--------------------------------------------------------

Now, when I use the library, I have to derive from 'foo' to make it
useful. I also have to add a new function which is *not* declared
virtual in 'foo':

----------------------- my code ------------------------
class myfoo : public foo {
...
void myfunc(void);
}
--------------------------------------------------------

Problem: if I know that a 'fooref' actually points to a 'myfoo', how
do I call 'myfunc'?

void a(fooref b) {
b->myfunc(); // compiler error: foo has no myfunc
static_cast<myfooref>(b)->myfunc(); // 1
static_cast<myfoo *>(&*b)->myfunc(); // 2
}

Both (1) and (2) compile, but are they the same thing? I understand
(2), but (1) is more confusing. Can I cast a templated class in this
way?

Cheers

AL
Jul 23 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
On 2005-06-27, Andy Lomax <abuse@[> wrote:
I'm using a library where the supplier has provided base class 'foo',
and a reference counting class which wraps 'foo':

------------------- library code -----------------------
template<class T>
refcount {
... // reference counting wrapper; like shared_ptr
};

class foo {
...
};

typedef refcount<foo> fooref;
--------------------------------------------------------

Now, when I use the library, I have to derive from 'foo' to make it
useful. I also have to add a new function which is *not* declared
virtual in 'foo':

----------------------- my code ------------------------
class myfoo : public foo {
...
void myfunc(void);
}
--------------------------------------------------------

Problem: if I know that a 'fooref' actually points to a 'myfoo', how
do I call 'myfunc'?

void a(fooref b) {
b->myfunc(); // compiler error: foo has no myfunc
static_cast<myfooref>(b)->myfunc(); // 1
static_cast<myfoo *>(&*b)->myfunc(); // 2
}

Both (1) and (2) compile, but are they the same thing? I understand
(2), but (1) is more confusing. Can I cast a templated class in this
way?


You can't generally cast anything to anything, no (and the different
parametrizations *are* allowed to be as unrelated as you like -- for example,
you could specialise one of them to inherit from vector<int>, and another to
inherit list<void*> if you wanted to). Depending on what conversion operators
refcount supports, it might work.

Now some thoughts --
(1) If you're casting down a class heirarchy, it would be safer to use a
dynamic cast. Then you get a runtime check to make sure you are really right
(and that it does really point to what you think it does)

(2) But it's better to avoid this. What is stopping you from making void a()
take a parameter of type myfoo instead ? If you've got several derived classes
of foo, you could factor them into a common base class. There are legitimate
uses for downtime casting, but the abuses are more common than the uses.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 23 '05 #2

P: n/a
On Mon, 27 Jun 2005 12:14:57 +0000 (UTC), Donovan Rebbechi
<ab***@aol.com> wrote:
You can't generally cast anything to anything, no (and the different
parametrizations *are* allowed to be as unrelated as you like -- for example,
you could specialise one of them to inherit from vector<int>, and another to
inherit list<void*> if you wanted to). Depending on what conversion operators
refcount supports, it might work.
Ah.. forgotten about conversion operators. I've checked refcount, and
the only conversion op it has is:

template<class T>
class refcount {
operator T* () const { return static_cast<T*>(ref->ptr); }
};

So the code compiles anyway even without a conversion operator.
Now some thoughts --
(1) If you're casting down a class heirarchy, it would be safer to use a
dynamic cast. Then you get a runtime check to make sure you are really right
(and that it does really point to what you think it does)
Thanks. Presumably the dynamic_cast overhead is higher, though, so I
should stick with static_cast if I can guarantee no problems?
(2) But it's better to avoid this. What is stopping you from making void a()
take a parameter of type myfoo instead ? If you've got several derived classes
of foo, you could factor them into a common base class. There are legitimate
uses for downtime casting, but the abuses are more common than the uses.
Two reasons:
(a) the base 'foo' provides a lot of routines that I need, and they
all return a 'fooref', so I can't assign the result to a
refcount<myfoo> without downcasting anyway (ie. the problem just
moves):

typedef refcount<myfoo> myfooref;

void a(myfooref b) {
b->myfunc(); // Ok; solves immediate problem, but...
myfooref c = b->x(); // doesn't compile: x returns a fooref
myfooref d = static_cast<myfooref>(b->x()); // Ok
}

(b) This is a bit more nebulous. I'm not sure why, but it seems to me
that my own code should be written to use the original base class as
much as possible, rather than forcing use of my own subclass.
If you've got several derived classes
of foo, you could factor them into a common base class.


As it happens, the library provides 'foo'; I derive 'myfoo' from it; I
then derive another 60-odd classes from 'myfoo'.

Cheers

AL
Jul 23 '05 #3

P: n/a
On 2005-06-27, Andy Lomax <abuse@[> wrote:
On Mon, 27 Jun 2005 12:14:57 +0000 (UTC), Donovan Rebbechi Two reasons:
(a) the base 'foo' provides a lot of routines that I need, and they
all return a 'fooref', so I can't assign the result to a
refcount<myfoo> without downcasting anyway (ie. the problem just
moves):

typedef refcount<myfoo> myfooref;

void a(myfooref b) {
b->myfunc(); // Ok; solves immediate problem, but...
myfooref c = b->x(); // doesn't compile: x returns a fooref
myfooref d = static_cast<myfooref>(b->x()); // Ok
}
My first thought was covariant return types, but of course that's not
going to work because the return value isn't a pointer, it's a smart
pointer.
(b) This is a bit more nebulous. I'm not sure why, but it seems to me
that my own code should be written to use the original base class as
much as possible, rather than forcing use of my own subclass.
If you've got several derived classes
of foo, you could factor them into a common base class.


As it happens, the library provides 'foo'; I derive 'myfoo' from it; I
then derive another 60-odd classes from 'myfoo'.


Sounds like a good way to do it.

I wonder if there's a way you could contain the problem ? For example, by
writing a class whose responsibility is to take care of the downcasting.
It's a similar idea to auto_ptr or even scoped_ptr -- the point of the
class is to encapsulate the potentially dangerous operation (in this case,
downcasting). You'd implement it by giving it the same interface as myfoo,
except functions that return fooref would be adapted to return myfooref.
You could do this via private inheritance for example, and just delegate
calls to the contained myfooref object.

Cheers,
--
Donovan Rebbechi
http://pegasus.rutgers.edu/~elflord/
Jul 23 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.