PDA

View Full Version : Virtual method segfault (C++)


sealfin
2006.12.03, 09:02 AM
Okay, I'm currently putting together a UI for a game, and I've run into a minor problem - I have a 'roundedDialog' class which inherits from a foundational 'dialog' class; the dialog class has a virtual 'Render()' method, which the roundedDialog class overrides to render the pretty rounded rect which gives it its name...

The problem is that the Render() method of roundedDialog must call the Render() method of dialog to render any content of the dialog (which is private to roundedDialog); I thought the easiest way to do this would be to cast the 'this' pointer and call the method after rendering the rounded rect...

(( dialog* )this )->Render();

...except the code segfaults; now I could just add a public/protected RenderParent() method to dialog which would wrap the Render() method, and call that instead, but I'm wondering what the correct way of overcoming this problem would be (say if in the future I encounter the problem with a library I don't have the source to) - any C++ gurus care to enlighten me? :)

As my long-winded explanation probably makes little sense, I've just posted the two classes from the test-case...

class One
{
public:
virtual void Hello( void )
{
printf( "Hello!\n" );
return;
};
};

class Two : public One
{
public:
virtual void Hello( void )
{
(( One* )this )->Hello();
printf( "Whiskey tango foxtrot?\n" );
return;
};
};

Cochrane
2006.12.03, 11:44 AM
I'm not sure if I understood correctly what you mean. If I did, you should try with One::Hello() to invoke the superclasses's implementation (similar to a message to super in Objective-C). Your example would be, using this:

class Two : public One
{
public:
virtual void Hello( void )
{
One::Hello();
printf( "Whiskey tango foxtrot?\n" );
return;
};
};

(class One would need no modification)

sealfin
2006.12.03, 11:48 AM
Thanks Cochrane, that's what I was looking for! :D

OneSadCookie
2006.12.03, 03:46 PM
Not sure if it's relevant, but you must be very careful with pointers to objects in C++ where multiple inheritance is involved, since casts between base classes won't give the same pointer:

#include <stdio.h>

class A { int x; };
class B { int y; };
class C : public A, B { int z; };

int main(int argc, const char *argv[]) {
C *c = new C;
printf("c = %p\n", c);
printf("(A*)c = %p\n", (A*)c);
printf("(B*)c = %p\n", (B*)c);
printf("(B*)(void*)c = %p // do not, *ever* do this\n", (B*)(void*)c);
printf("(C*)(B*)c = %p\n", (C*)(B*)c);
return 0;
}

iMacCoreDuo:~/Desktop keith$ g++ test.cpp
iMacCoreDuo:~/Desktop keith$ ./a.out
c = 0x3002f0
(A*)c = 0x3002f0
(B*)c = 0x3002f4
(B*)(void*)c = 0x3002f0 // do not, *ever* do this
(C*)(B*)c = 0x3002f0

sealfin
2006.12.04, 07:10 AM
you must be very careful with pointers to objects in C++ where multiple inheritance is involved, since casts between base classes won't give the same pointer

Yeah, I'd already thought that might be the case, but I didn't/don't know enough about how C++ compiles to be certain; casting to a base class however seems to work for calling regular methods of a superclass, which is why I thought casting to call virtual methods of a superclass might work, before I realised that would defeat the purpose of having virtual methods...

#include <stdio.h>

class ParentOne
{
public:
void Say( void )
{
printf( "Hello" );
return;
};
};

class ParentTwo
{
public:
void Say( void )
{
printf( "World" );
return;
};
};

class Child : private ParentOne, private ParentTwo
{
public:
void Say( void )
{
((ParentOne* )this )->Say();
printf( " " );
((ParentTwo* )this )->Say();
printf( "\nWhiskey tango foxtrot?\n" );
return;
};
};

int main( int argc, char *argv[] )
{
Child o1, *o2;
o1.Say();
o2 = new Child();
o2->Say();
delete o2;
return 0;
}