|
Boost : |
From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-12-10 17:24:59
>From: "Johan Nilsson" <johan.nilsson_at_[hidden]>
> "Terje Slettebø" <tslettebo_at_[hidden]> wrote in message
> >
> > Here are the results:
> >
> > MSVC 6 - vptr at 0 - It works
> > Intel C++ 7.0 - vptr at 0 - It works
> > g++ 2.95.3 - vptr _not_ at zero - boom! :) It gives an OS protection
error
> > at the point of dynamic_cast
> > BCB 6 - vptr _not_ at zero - boom! :) It gives an OS protection error at
> the
> > point of dynamic_cast
>
> I'd appreciate if you could try to (1) use this instead:
>
> Y *yptr=dynamic_void_cast<Y>(static_cast<void*>(&y));
As a matter of fact, the original test I had was more elaborate, and
included calling virtual functions. However, I found that it crashed much
earlier, already in the call to dynamic_cast, where it likely tried to use a
value that pointed to outer space (the value of the "n" variable), to read
from a vtable. Therefore, I distilled it down to the above simple case. In
the case where it didn't crash, it also called the correct virtual function.
I used originally a test like this:
--- Start ---
class BaseA
{
public:
int n;
BaseA() : n(123) {}
};
class DerivedA : public BaseA
{
public:
virtual ~DerivedA() {}
virtual void f()
{
std::cout << "DerivedA::f()\n";
}
};
class BaseB
{
public:
virtual ~BaseB() {}
};
class DerivedB : public BaseB
{
public:
int n;
DerivedB() : n(123) {}
virtual void f()
{
std::cout << "DerivedB::f()\n";
}
};
int main()
{
DerivedA a;
DerivedB b;
void *aptr=&a;
void *bptr=&b;
DerivedA *newaptr=dynamic_void_cast<DerivedA>(aptr);
DerivedB *newbptr=dynamic_void_cast<DerivedB>(bptr);
newaptr->f();
newbptr->f();
}
--- End ---
I then trimmed it down.
Therefore, I don't think a static_cast to void *, before calling
dynamic_static_cast, will make any difference, as I used the (implicit)
conversion to void *, earlier, and in the last example. I tried it now (only
on g++), and it made no difference. It still crashed like before.
> and (2) add a virtual destructor to X. What are the results?
Actually, that made no difference, either (still on g++). However, case B
(DerivedB) above here succeeds. The difference is this:
Fails:
struct X { ~X() {} int n; };
struct Y : X {};
Succeeds:
struct X { ~X() {} };
struct Y : X { int n; };
Basically, this is messy. Don't go there. :)
> > This also means that its signature is different from dynamic_cast, and
> that
> > it therefore can't be used for casting references (unlike dynamic_cast).
> >
>
> That was because I couldn't imagine a 'void&', or did I miss something?
No, I don't think you missed anything. When thinking about generalising it
to include references, as well, I came to the same as you. There's no void
&.
Regards,
Terje
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk