Re: [Flightgear-devel] C++ question - solved
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Thanks for all the replies. They brought me on the right track. The solution I've got now is also known as the Barton and Nackman Trick. It's a bit pervert - but totaly legal C++ code: templatetypename leaftype class A { leaftype asLeaf() { return static_castleaftype(*this); } public: bool foo( leaftype bar ) { return asLeaf().foo( bar ); } }; class B : public AB { public: bool foo( B bar ) { return /*...*/; } } The Barton and Nackman trick is important to avoid virtual function where they are too slow (i.e. when the additional pointer lookup hurts performance) CU, Christian Paul Kahler schrieb: It sounds to me like you should just drop the virtual function declaration in the abstract A class (or make it non-virtual). It serves no purpose other than trying to enforce your design on the subclasses. Since you require the foo() function to take a parameter of the subclass type, only a B can foo a B, and only a C can foo a C. Let us not use complex language constructs (templates for example) just to allow the compiler to check that you're following your own convention. Put a comment in the base class that defines this requirement on subclasses and call it a day. OTOH, if generic code is going to tell an X to foo another X (somehow knowing they are the same type) this might not work. H. I think another option is to declare A:foo(A p1) and then have the B class explicitly cast the parameter p1 to a B inside B:foo when using the B-specific functionality of the parameter. I don't know how to do templates, so this is what I might do until it got too ugly. Hope that helps, Paul On Sat, 2005-01-15 at 15:12 +0100, Christian Mayer wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi, can someone help me to solve thise problem: Imagine I've got this class hierachy: class A { virtual bool foo( A bar ) = 0; } class B : A { bool foo( B bar ) { ... } } int main( void ) { B foobar; } this won't compile as my class B is still abstract as I didn't provide a bool foo( A bar ) member. But I only want class A to be an interface that tells everybody what to expect from it's derivated classes. And one of these things is, that every child must have a member that is called foo and has one parameter of the type of the child itself. How do I achieve that? The only workaround I can come up with is, that I have: class B { friend bool foo( class B, class B ); } bool foo( class B bar1, class B bar2 ) { ... } I this doesn't guarantee me, that every child of A must have a foo function... Thanks, Christian ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.0 (MingW32) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFB7nR5lhWtxOxWNFcRArQdAJ9CFcrVXvlEeUszuzoRmbB/ACJU6wCfdsSA RYAAKsDENV2fQj0Qn5d2KpE= =pyGn -END PGP SIGNATURE- ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
Re: [Flightgear-devel] C++ question - solved
On Wednesday 19 January 2005 06:53, Christian Mayer wrote: Thanks for all the replies. They brought me on the right track. The solution I've got now is also known as the Barton and Nackman Trick. It's a bit pervert - but totaly legal C++ code: templatetypename leaftype class A { leaftype asLeaf() { return static_castleaftype(*this); } public: bool foo( leaftype bar ) { return asLeaf().foo( bar ); } }; class B : public AB { public: bool foo( B bar ) { return /*...*/; } } The Barton and Nackman trick is important to avoid virtual function where they are too slow (i.e. when the additional pointer lookup hurts performance) CU, Christian Thanks for sharing this. This prompted me to go look at my copy of Barton and Nackman (Scientific and Engineering C++). Reminds that it is a rather good book and I should read it more often. But I couldn't find this trick in more than a half day trying. Richard Harke ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
Re: [Flightgear-devel] C++ question
It sounds to me like you should just drop the virtual function declaration in the abstract A class (or make it non-virtual). It serves no purpose other than trying to enforce your design on the subclasses. Since you require the foo() function to take a parameter of the subclass type, only a B can foo a B, and only a C can foo a C. Let us not use complex language constructs (templates for example) just to allow the compiler to check that you're following your own convention. Put a comment in the base class that defines this requirement on subclasses and call it a day. OTOH, if generic code is going to tell an X to foo another X (somehow knowing they are the same type) this might not work. H. I think another option is to declare A:foo(A p1) and then have the B class explicitly cast the parameter p1 to a B inside B:foo when using the B-specific functionality of the parameter. I don't know how to do templates, so this is what I might do until it got too ugly. Hope that helps, Paul On Sat, 2005-01-15 at 15:12 +0100, Christian Mayer wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Hi, can someone help me to solve thise problem: Imagine I've got this class hierachy: class A { virtual bool foo( A bar ) = 0; } class B : A { bool foo( B bar ) { ... } } int main( void ) { B foobar; } this won't compile as my class B is still abstract as I didn't provide a bool foo( A bar ) member. But I only want class A to be an interface that tells everybody what to expect from it's derivated classes. And one of these things is, that every child must have a member that is called foo and has one parameter of the type of the child itself. How do I achieve that? The only workaround I can come up with is, that I have: class B { friend bool foo( class B, class B ); } bool foo( class B bar1, class B bar2 ) { ... } I this doesn't guarantee me, that every child of A must have a foo function... Thanks, Christian ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
Re: [Flightgear-devel] C++ question
On Sat, 15 Jan 2005 15:12:57 +0100, Christian Mayer [EMAIL PROTECTED] wrote: But I only want class A to be an interface that tells everybody what to expect from it's derivated classes. And one of these things is, that every child must have a member that is called foo and has one parameter of the type of the child itself. How do I achieve that? You'll have to start messing around with templates -- it won't be too clean, though. All the best, David -- http://www.megginson.com/ ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
Re: [Flightgear-devel] C++ question
Hello Christian, If I understand your problem right, you could use class pointers (but you won't achieve strong typing at compile time), or templates. TEMPLATE EXAMPLE: template class T class A { virtual void foo(T param); }; CLASS POINTER EXAMPLE: class A { public: virtual void foo(A* param); }; class B : A { virtual void foo(A* param) { B* cast = dynamic_castB*(a); if (cast) { ... } } }; cheers, Manuel ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
Re: [Flightgear-devel] C++ question
Christian Mayer wrote: But I only want class A to be an interface that tells everybody what to expect from it's derivated classes. And one of these things is, that every child must have a member that is called foo and has one parameter of the type of the child itself. How do I achieve that? With a template. But IMHO you really don't want to go there. :) Basically, you make a class template with a function parametrized on the type of the class. The problem is that this kind of template wizardry is confusing and hard. You had to ask how to do it, which means that most people who see it are going to have to look it up before understanding it. Andy ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
Re: [Flightgear-devel] C++ question
template class T class A { virtual void foo(T param); }; Maybe I should add how to derive the class B from the template: class B : public AB { ... }; bye, Manuel ___ Flightgear-devel mailing list Flightgear-devel@flightgear.org http://mail.flightgear.org/mailman/listinfo/flightgear-devel 2f585eeea02e2c79d7b1d8c4963bae2d
Re: [Flightgear-devel] C++ question...
On Tuesday, 11 November 2003 00:47, Gene Buckle wrote: I see code like this: limit_value (double * value, const SGPropertyNode * arg) .and wonder about the placement of the pointer operator. C syntax : type *p C++ syntax : type* p The compiler doesn't care which you use. They both mean the same thing. Why the extra whitespace in the declaration? Cause some developer felt like coding that way. (I don't like his/her style but it's still valid) The compiler knows that it's not multiplication because it is a type declaration. Remove the type and it would mean multiplication. The same rule applies to multiplying integer/floating point variables. a* b = a *b = a * b The compiler knows the difference between variables and types. Paul ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel
Re: [Flightgear-devel] C++ question...
Thanks for the clue Paul. :) g. On Tue, 11 Nov 2003, Paul Surgeon wrote: On Tuesday, 11 November 2003 00:47, Gene Buckle wrote: I see code like this: limit_value (double * value, const SGPropertyNode * arg) .and wonder about the placement of the pointer operator. C syntax : type *p C++ syntax : type* p The compiler doesn't care which you use. They both mean the same thing. Why the extra whitespace in the declaration? Cause some developer felt like coding that way. (I don't like his/her style but it's still valid) The compiler knows that it's not multiplication because it is a type declaration. Remove the type and it would mean multiplication. The same rule applies to multiplying integer/floating point variables. a* b = a *b = a * b The compiler knows the difference between variables and types. Paul ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel
Re: [Flightgear-devel] C++ question...
On 11/10/03 at 2:47 PM Gene Buckle wrote: I see code like this: limit_value (double * value, const SGPropertyNode * arg) .and wonder about the placement of the pointer operator. I would think the above would be functionally different than: limit_value (double *value, const SGPropertyNode *arg) I think of the multiplication operator when I see whitespace after the *, but I know(for small values of know) that if it were really parsed as trying to multiply a variable by a variable type, the parser would throw a fit. Why the extra whitespace in the declaration? The extra whitespace is irrelevent. Personally I prefer int* ip; since I like to think of ip as an int-pointer. Kernighan and Richie specifically say in The C Programming Language though that they like to write int *ip; since it reinforces the point that dereferencing ip (*ip) gives an int. Cheers - Dave ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel
Re: [Flightgear-devel] C++ question...
Personally I prefer int* ip; That would turn me into a gibbering idiot. :) Kernighan and Richie specifically say in The C Programming Language though that they like to write int *ip; since it reinforces the point that dereferencing ip (*ip) gives an int. Now THAT makes sense. You have to understand though, the last time I wrote anything serious in C, the only way to define functions was this: main(argc, argv) int *argc; char **argv; { } ...note that it's been *years* since I had more than a passing accquaintance(sp) with main() so I probably got the parameters backwards... g. ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel
Re: [Flightgear-devel] C++ Question/Problem, WRT New Sky Code
Huzzah! I can run again! Thanks for the help, Jonathan Polley On Thursday, September 19, 2002, at 07:09 AM, Norman Vine wrote: Jonathan Polley I did see this code block in SkySceneLoader.cpp (I assume that it is global data): // Need to add a light here until we figure out how to use the sun position and color SkyLight::SkyLightType eType = SkyLight::SKY_LIGHT_DIRECTIONAL; SkyLight *pLight = new SkyLight(eType); Is there any way I can defer this until after the main() starts? Good catch :-) try something like SkyLight *pLight = NULL; bool SkySceneLoader::Load(std::string filename) { if ( !pLight ) { pLight = new SkyLight(eType); if( !pLight) DO SOMETHING DRASTIC } SkyArchive archive; . ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel
Re: [Flightgear-devel] C++ Question/Problem, WRT New Sky Code
From: Jonathan Polley [EMAIL PROTECTED] When I rebuilt the MacOS X version of FlightGear, after the 3D cloud code was added, I started getting an EXC_BAD_ACCESS runtime error. I did some looking around with gdb and found out that the error was happening BEFORE the main was being called. Program received signal EXC_BAD_ACCESS, Could not access memory. 0x90989544 in glGetIntegerv () (gdb) backtrace #0 0x90989544 in glGetIntegerv () #1 0x002130b8 in SkyTextureState::SkyTextureState() (this=0x41e0478) at SkyTextureState.cpp:47 #2 0x00212814 in SkyMaterial::SkyMaterial() (this=0x41e03d0) at SkyMaterial.cpp:60 #3 0x0016df60 in SkyLight::SkyLight(SkyLight::SkyLightType) (this=0x0, Very strange ! eType=3221223248) at SkyLight.cpp:67 ^^ Strange too ! #4 0x003167c4 in __static_initialization_and_destruction_0(int, int) () #5 0x8fe16594 in __dyld_call_module_initializers_for_objects () #6 0x8fe160a0 in __dyld_call_module_initializers () #7 0x8fe133ac in __dyld__dyld_make_delayed_module_initializer_calls () #8 0x2c04 in _call_mod_init_funcs () at /SourceCache/Csu/Csu-45/crt.c:299 #9 0x2aec in _start (argc=1, argv=0xbc54, envp=0xbc5c) at /SourceCache/Csu/Csu-45/crt.c:217 #10 0x2a4c in start () How is this possible? If this were Ada, I would say that it is happening during Elaboration, but I'm not sure if C++ has something similar. SkyLight::SkyLight is creating a new instance of SkyMaterial, and my bet is that glGetIntegerv is having the problem because OpenGL hasn't been initialized yet. I don't looked at the code but it seems that there is a SkyLight global variable (or a static member one) defined. However, the fact that the constructor is called with a this null pointer seems odd to me. Cheers, -Fred ___ Flightgear-devel mailing list [EMAIL PROTECTED] http://mail.flightgear.org/mailman/listinfo/flightgear-devel