inheritance question

  • Thread starter Thread starter Bruno van Dooren
  • Start date Start date
B

Bruno van Dooren

Hi all,

I have 2 classes:
class A{...};
class B : public A{...}

i manage all B instances in an array of A*.
A is a generic type that serves as a base type for a resource manager.

when i try to do

B* objectReference = dynamic_cast<B*>(aPointerToAnInstanceOfA);

i get compiler error:
error C2683: dynamic_cast : 'ManagedResource' is not a polymorphic type

apparently it is not enough that B inherits from A.
is there an elegant solution to this? or do i need to create a virtual dummy
method, however silly that would be?

kind regards,
Bruno.
 
Bruno said:
Hi all,

I have 2 classes:
class A{...};
class B : public A{...}

i manage all B instances in an array of A*.
A is a generic type that serves as a base type for a resource manager.

when i try to do

B* objectReference = dynamic_cast<B*>(aPointerToAnInstanceOfA);

i get compiler error:
error C2683: dynamic_cast : 'ManagedResource' is not a polymorphic
type

apparently it is not enough that B inherits from A.
is there an elegant solution to this? or do i need to create a
virtual dummy method, however silly that would be?

You need to have at least one virtual method for dynamic_cast to succeed.
Normally, in a structure such as you describe, your 'A' class should at
least have a virtual destructor.

-cd
 
I have 2 classes:
class A{...};
class B : public A{...}

i manage all B instances in an array of A*.
A is a generic type that serves as a base type for a resource manager.

when i try to do

B* objectReference = dynamic_cast<B*>(aPointerToAnInstanceOfA);

i get compiler error:
error C2683: dynamic_cast : 'ManagedResource' is not a polymorphic type

apparently it is not enough that B inherits from A.
is there an elegant solution to this? or do i need to create a virtual dummy
method, however silly that would be?


An anal C++ programmer would tell you that if you need to cast your design
is broken. I usually tend to agree with that theory... How would you know
that aPointerToAnInstanceOfA really is a B instance? It almost has to do
with some twisted trick...

As to why this error occurs, did you look at the help of error message
C2683? Here it is :

====================
Compiler Error C2683

dynamic_cast : 'class' is not a polymorphic type

The dynamic_cast operator cannot be used to convert from a non-polymorphic
class, that is, a class that does not define any virtual functions.

You can use the static_cast operator to perform conversions of
non-polymorphic types; note, however, that static_cast does not perform a
run-time check.

The following is an example of this error:

class B { };
class D : public B { };

void f(B* pb)
{
D* pd1 = dynamic_cast<D*>(pb); // error
}
====================

I don't know the reason of this "limitation" though. I would have expected
this to work well. I would simply put the destructor of A virtual...

BTW: You might be interrested to know dynamic_cast, even though it's
standard C++, is not supported by all C++ compilers. I've had this problem
with Watcom on QNX a little while ago...

Alex.
 
dynamic_cast : 'class' is not a polymorphic type
The dynamic_cast operator cannot be used to convert from a non-polymorphic
class, that is, a class that does not define any virtual functions.

You can use the static_cast operator to perform conversions of
non-polymorphic types; note, however, that static_cast does not perform a
run-time check.

While static_cast doesn't do a runtime check, it at least prevents you
from casting to something that is compltely impossible, that a C-style
or reinterpret_cast would let you do. If you know that an A* object is
really a B*, then static_cast is definitely a (relatively) safe fast way
to do it.
 
While static_cast doesn't do a runtime check, it at least prevents you
from casting to something that is compltely impossible, that a C-style
or reinterpret_cast would let you do. If you know that an A* object is
really a B*, then static_cast is definitely a (relatively) safe fast way
to do it.

If there is multiple inheritance involved there can be big hickups with
static_cast or C-style cast... Here's an example I've been confronted with
recently.

#include <stdio.h>
#include <conio.h>

class Transport {
public:
virtual void Send() = 0;
virtual void Receive() = 0;
virtual void Wait() = 0;
};

class Client {
public:
virtual void Connect() = 0;
};

class TransportUDP : public Transport {
public:
virtual void Send() {
printf("TransportUDP::Send()\n");
}

virtual void Receive() {
printf("TransportUDP::Receive()\n");
}

virtual void Wait() {
printf("TransportUDP::Wait()\n");
}
};

class TransportUDPClient : public TransportUDP, public Client {
public:
virtual void Connect() {
printf("TransportUDPClient::Connect()\n");
}
};

void main(void) {
Transport *pTransport= new TransportUDPClient();

// This does not call TransportUDPClient::Connect()
// but TransportUDP::Send()
static_cast<Client*>(pTransport)->Connect();

pTransport->Wait();
pTransport->Receive();
pTransport->Send();

delete pTransport;

getch();
}


Even though pTransport actually points to a TransportUDPClient, thus Client
instance, only dynamic_cast would allow me to call the right function
(Connect)...

Alex.
 
Your code generated the following error:

foo.cpp(43) : error C2440: 'static_cast' : cannot convert from Transport
*' to 'Client *'
Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast


The static_cast failed, as it should have.
 
Your code generated the following error:
foo.cpp(43) : error C2440: 'static_cast' : cannot convert from Transport
*' to 'Client *'
Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast


The static_cast failed, as it should have.


Umm I actually hand modified the code a bit before sending it. Should have
tested it, sorry.

The actual code is using dynamic_cast, and works just fine. The initial code
was using a C-style cast, which compiled fine, but did not work as I
initially expected (it would call the wrong function).

I though I remembered using static_cast with the same results, but obviously
not!

Sorry again.

Alex.
 
Ahh well thats the difference right there. The C-style cast is evil :)
It attempts to do the equivalent of a static_cast, followed by a
const_cast, then reinterpret_cast if all else fails. The problem is,
when all else fails, reinterpret_cast is usually not what you want (in
C++ code). static_cast is substantially safer and using it all the
time lets you notice when you _really_ need to bust out a
reinterpret_cast and the necessary work to make THAT safe.
 
Bruno,

I think the fact that you encountered this issue is an indication that the
design is sub-optimal. The design should help you, not hinder you.

What is the reason for putting Connect in Client?

dan
 
Back
Top