Manuel Teira wrote:
[snip: example program]
OK, now , the results:
Solaris 10 . Sun CC Studio 12:
-bash-3.00$ ./typeid I'm adding myself to the poller as DispatchHandle*
In Poller, adding a handle of type: AsynchIO
In Dispatcher::run(), handle is a PollerHandle*
Assertion failed: dynamic_cast<Target>(x) == x, file typeid.cc, line 10
Abort (core dumped)
Linux 2.6. g++ 4.1.3:
$ ./typeid
I'm adding myself to the poller as P14DispatchHandle
In Poller, adding a handle of type: 8AsynchIO
In Dispatcher::run(), handle is a P12PollerHandle
DispatchHandle is 0x804b008 for handle: 0x804b008
The example works.
Furthermore, if I change the main() to avoid involving the AsyncIO class:
int main(int argc, char *argv[]) {
Poller poller;
DispatchHandle *dh = new DispatchHandle();
dh->run(poller);
Dispatcher dp;
dp.run();
}
The example works now:
I'm adding myself to the poller as DispatchHandle*
In Poller, adding a handle of type: DispatchHandle
In Dispatcher::run(), handle is a PollerHandle*
DispatchHandle is 29160 for handle: 29160
It also works if I just change the inheritance AsynchIO ->
DispatchHandle to public.
Any idea about what could be happening?
gcc and solaris are differing on the rules about casting to private bases. I'm
not certain if it's tecnically incorrect but a bit of googling strongly suggests
that we should not write code that depends on this, we will probably have
trouble with other compilers.
I think we need to make the inheritance public, or come up with an alternative
design that does not require a dynamic_cast to a private base class.
Andrew - is there any reason not to just make the inheritance public?
#include <iostream>
#include <assert.h>
using namespace std;
void *ptr;
template <class Target, class Source>
inline Target polymorphic_downcast(Source* x) {
assert(dynamic_cast<Target>(x) == x);
return static_cast<Target>(x);
}
class PollerHandle {
public:
virtual ~PollerHandle() {};
};
class Poller {
public:
void addFd(PollerHandle &handle) {
cout << "In Poller, adding a handle of type: "
<< typeid(handle).name() << endl;
ptr = &handle;
}
};
class DispatchHandle: public PollerHandle {
public:
virtual ~DispatchHandle() {};
void run(Poller &poller) {
cout << "I'm adding myself to the poller as " << typeid(this).name() << endl;
poller.addFd(*this);
}
};
class AsynchIO: private DispatchHandle {
public:
void start(Poller &poller) {
DispatchHandle::run(poller);
}
};
class Dispatcher {
public:
void run() {
PollerHandle *handle = static_cast<PollerHandle*>(ptr);
cout << "In Dispatcher::run(), handle is a "
<< typeid(*handle).name() << endl;
DispatchHandle *dh = polymorphic_downcast<DispatchHandle*>(handle);
cout << "DispatchHandle is " << dh << " for handle: " << handle << endl;
}
};
int main(int argc, char *argv[]) {
Poller poller;
AsynchIO *aio = new AsynchIO();
aio->start(poller);
Dispatcher dp;
dp.run();
struct A { virtual ~A() {}};
struct B : private A{} b;
A* pa = dynamic_cast<A*>(&b);
}