[Ns-developers] C++ virtual method overloading and inheritance = disaster?

Raj Bhattacharjea raj.b at gatech.edu
Tue Jul 8 17:39:40 PDT 2008


On Tue, Jul 8, 2008 at 7:29 PM, Gustavo Carneiro <gjcarneiro at gmail.com> wrote:
[snip]
> Compiling the above program I get:
>
> gjc at dark-tower:tmp$ g++ test.cc
> test.cc: In function 'int main()':
> test.cc:18: error: no matching function for call to 'UdpSocket::Bind(int)'
> test.cc:11: note: candidates are: virtual int UdpSocket::Bind()
>
> WTF?  How come a Bind() method in UdpSocket hides the other Bind() method
> defined in the base Socket class?

It doesn't, the C++ type system just isn't as smart as you assume it
is in this example.  You declared a UdpSocket, and if you look in your
UdpSocket struct, it only has a single API, just as the compiler
reports.  Because you declared a stack allocated UdpSocket, this is
the expected behavior.  To make the virtual magic happen, you need a
base class pointer pointing to a subclass.

>
> Commenting out the Bind() method in UdpSocket makes the program compile.
>

I don't believe this is the right approach, but I'm not a python
bindings guru.  More on this below.

> I bring this example this because this problem appears in NS-3, and Python
> bindings suffer.
>
[more code snipped]
>
> Now, what happens next.  When I call socketFactory.CreateSocket () from
> Python, the Python bindings know that the method is supposed to return
> Socket*.  However, they also know that there exists a known public class
> UdpSocket, and use C++ RTTI (typeid(*pointer)) to discover this is actually
> a UdpSocket object, not a Socket.  Finally, when I call socket.Bind
> (address) from Python, the call fails because apparently only one Bind()
> method exists, and not the other.

This seems to be the error to me...in order to make C++ virtual
methods and inherticance work just so, you NEED to use the base class
pointer.  Is this downcast using the RTTI a necessary feature of the
bindings?  If you don't downcast, your problems are solved.  That is,
using the following code for your example main does exactly what you
want, because the base class is what contains ALL the info about the
virtual API:

int main(void)
{
	Socket* sock = new UdpSocket();
	sock->Bind (123);
}

>
> A long story just to explain why we need to fix UdpSocket, adding the
> missing Bind method.  And to vent some of my frustration at this (having
> spent some hours trying to support this use case in PyBindGen only to find
> out that C++ itself does not support it :P).

To reiterate, I think that C++ does support this case just fine, its
the downcasting you do based upon the RTTI that is the issue.  Just
call the API on the base class pointer.

-- 
Raj Bhattacharjea
Georgia Institute of Technology
School of Electrical and Computer Engineering
Systems Analyst
404.894.2955


More information about the Ns-developers mailing list